Blame view

src/components/tabs/tabs.vue 7.61 KB
871ed4d8   梁灏   init Tabs component
1
  <template>
17f52abf   梁灏   update Tabs
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
      <div :class="classes">
          <div :class="[prefixCls + '-bar']">
              <div :class="[prefixCls + '-nav-container']">
                  <div :class="[prefixCls + '-nav-wrap']">
                      <div :class="[prefixCls + '-nav-scroll']">
                          <div :class="[prefixCls + '-nav']" v-el:nav>
                              <div :class="barClasses" :style="barStyle"></div>
                              <div :class="tabCls(item)" v-for="item in navList" @click="handleChange($index)">
                                  <Icon v-if="item.icon !== ''" :type="item.icon"></Icon>
                                  {{ item.label }}
                                  <Icon v-if="closable && type === 'card'" type="ios-close-empty" @click.stop="handleRemove($index)"></Icon>
                              </div>
                          </div>
                      </div>
                  </div>
              </div>
          </div>
          <div :class="contentClasses" :style="contentStyle"><slot></slot></div>
      </div>
871ed4d8   梁灏   init Tabs component
21
22
  </template>
  <script>
17f52abf   梁灏   update Tabs
23
24
25
26
27
      import Icon from '../icon/icon.vue';
      import { oneOf, getStyle } from '../../utils/assist';
  
      const prefixCls = 'ivu-tabs';
  
871ed4d8   梁灏   init Tabs component
28
      export default {
17f52abf   梁灏   update Tabs
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
          components: { Icon },
          props: {
              activeKey: {
                  type: [String, Number]
              },
              type: {
                  validator (value) {
                      return oneOf(value, ['line', 'card']);
                  },
                  default: 'line'
              },
              size: {
                  validator (value) {
                      return oneOf(value, ['small', 'default']);
                  },
                  default: 'default'
              },
              animated: {
                  type: Boolean,
                  default: true
              },
              closable: {
                  type: Boolean,
                  default: false
              }
          },
871ed4d8   梁灏   init Tabs component
55
          data () {
17f52abf   梁灏   update Tabs
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
              return {
                  prefixCls: prefixCls,
                  navList: [],
                  barWidth: 0,
                  barOffset: 0
              }
          },
          computed: {
              classes () {
                  return [
                      `${prefixCls}`,
                      {
                          [`${prefixCls}-card`]: this.type === 'card',
                          [`${prefixCls}-mini`]: this.size === 'small' && this.type === 'line',
                          [`${prefixCls}-no-animation`]: !this.animated
                      }
                  ]
              },
              contentClasses () {
                  return [
                      `${prefixCls}-content`,
77bafb31   梁灏   update Tabs
77
78
79
                      {
                          [`${prefixCls}-content-animated`]: this.animated
                      }
17f52abf   梁灏   update Tabs
80
81
82
83
84
                  ]
              },
              barClasses () {
                  return [
                      `${prefixCls}-ink-bar`,
77bafb31   梁灏   update Tabs
85
86
87
                      {
                          [`${prefixCls}-ink-bar-animated`]: this.animated
                      }
17f52abf   梁灏   update Tabs
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
                  ]
              },
              contentStyle () {
                  const x = this.navList.findIndex((nav, index) => nav.key === this.activeKey);
                  const p = x === 0 ? '0%' : `-${x}00%`;
  
                  let style = {};
                  if (x > -1) {
                      style = {
                          transform: `translateX(${p}) translateZ(0px)`
                      }
                  }
                  return style;
              },
              barStyle () {
                  let style = {
                      display: 'none',
77bafb31   梁灏   update Tabs
105
                      width: `${this.barWidth}px`
17f52abf   梁灏   update Tabs
106
107
                  };
                  if (this.type === 'line') style.display = 'block';
77bafb31   梁灏   update Tabs
108
109
110
111
112
                  if (this.animated) {
                      style.transform = `translate3d(${this.barOffset}px, 0px, 0px)`;
                  } else {
                      style.left = `${this.barOffset}px`;
                  }
17f52abf   梁灏   update Tabs
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
                  return style;
              }
          },
          methods: {
              getTabs () {
                  return this.$children.filter(item => item.$options.name === 'TabPane');
              },
              updateNav () {
                  this.navList = [];
                  this.getTabs().forEach((pane, index) => {
                      this.navList.push({
                          label: pane.label,
                          icon: pane.icon || '',
                          key: pane.key || index,
                          disabled: pane.disabled
                      });
                      if (!pane.key) pane.key = index;
                      if (index === 0) {
                          if (!this.activeKey) this.activeKey = pane.key || index;
                      }
                  });
77bafb31   梁灏   update Tabs
135
                  this.updateStatus();
17f52abf   梁灏   update Tabs
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
                  this.updateBar();
              },
              updateBar () {
                  this.$nextTick(() => {
                      const index = this.navList.findIndex((nav, index) => nav.key === this.activeKey);
                      const prevTabs = this.$els.nav.querySelectorAll(`.${prefixCls}-tab`);
                      const tab = prevTabs[index];
                      this.barWidth = parseFloat(getStyle(tab, 'width'));
  
                      if (index > 0) {
                          let offset = 0;
                          const gutter = this.size === 'small' ? 0 : 16;
                          for (let i = 0; i < index; i++) {
                              offset += parseFloat(getStyle(prevTabs[i], 'width')) + gutter;
                          }
  
                          this.barOffset = offset;
                      } else {
                          this.barOffset = 0;
                      }
                  });
              },
77bafb31   梁灏   update Tabs
158
159
160
161
              updateStatus () {
                  const tabs = this.getTabs();
                  tabs.forEach(tab => tab.show = (tab.key === this.activeKey) || this.animated);
              },
17f52abf   梁灏   update Tabs
162
163
164
165
166
167
168
169
170
171
172
173
174
              tabCls (item) {
                  return [
                      `${prefixCls}-tab`,
                      {
                          [`${prefixCls}-tab-disabled`]: item.disabled,
                          [`${prefixCls}-tab-active`]: item.key === this.activeKey
                      }
                  ]
              },
              handleChange (index) {
                  const nav = this.navList[index];
                  if (nav.disabled) return;
                  this.activeKey = nav.key;
77bafb31   梁灏   update Tabs
175
                  this.updateStatus();
17f52abf   梁灏   update Tabs
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
                  this.$emit('on-click', nav.key);
              },
              handleRemove (index) {
                  const tabs = this.getTabs();
                  const tab = tabs[index];
                  tab.$destroy(true);
  
                  if (tab.key === this.activeKey) {
                      const newTabs = this.getTabs();
                      let activeKey = -1;
  
                      if (newTabs.length) {
                          const leftNoDisabledTabs = tabs.filter((item, itemIndex) => !item.disabled && itemIndex < index);
                          const rightNoDisabledTabs = tabs.filter((item, itemIndex) => !item.disabled && itemIndex > index);
  
                          if (rightNoDisabledTabs.length) {
                              activeKey = rightNoDisabledTabs[0].key;
                          } else if (leftNoDisabledTabs.length) {
                              activeKey = leftNoDisabledTabs[leftNoDisabledTabs.length - 1].key;
                          } else {
                              activeKey = newTabs[0].key;
                          }
                      }
                      this.activeKey = activeKey;
                  }
                  this.$emit('on-tab-remove', tab.key);
                  this.updateNav();
              }
          },
          compiled () {
              this.updateNav();
871ed4d8   梁灏   init Tabs component
207
          },
17f52abf   梁灏   update Tabs
208
209
210
211
212
          watch: {
              activeKey () {
                  this.updateBar();
              }
          }
871ed4d8   梁灏   init Tabs component
213
214
      }
  </script>