871ed4d8
梁灏
init Tabs component
|
1
|
<template>
|
17f52abf
梁灏
update Tabs
|
2
3
|
<div :class="classes">
<div :class="[prefixCls + '-bar']">
|
be3fbd24
marxy
Tabs add scroll
|
4
|
<div :class="[prefixCls + '-nav-right']" v-if="showSlot"><slot name="extra"></slot></div>
|
17f52abf
梁灏
update Tabs
|
5
|
<div :class="[prefixCls + '-nav-container']">
|
be3fbd24
marxy
Tabs add scroll
|
6
7
8
9
10
|
<div ref="navWrap" :class="[prefixCls + '-nav-wrap', scrollable ? prefixCls + '-nav-scrollable' : '']" >
<span :class="[prefixCls + '-nav-prev', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollPrev"><Icon type="chevron-left"></Icon></span>
<span :class="[prefixCls + '-nav-next', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollNext"><Icon type="chevron-right"></Icon></span>
<div ref="navScroll" :class="[prefixCls + '-nav-scroll']">
<div ref="nav" :class="[prefixCls + '-nav']" class="nav-text" :style="navStyle">
|
17f52abf
梁灏
update Tabs
|
11
|
<div :class="barClasses" :style="barStyle"></div>
|
30510c3d
梁灏
support Tabs
|
12
|
<div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)">
|
17f52abf
梁灏
update Tabs
|
13
|
<Icon v-if="item.icon !== ''" :type="item.icon"></Icon>
|
1f974700
Aresn
Tabs support rend...
|
14
15
|
<Render v-if="item.labelType === 'function'" :render="item.label"></Render>
<template v-else>{{ item.label }}</template>
|
30510c3d
梁灏
support Tabs
|
16
|
<Icon v-if="showClose(item)" type="ios-close-empty" @click.native.stop="handleRemove(index)"></Icon>
|
17f52abf
梁灏
update Tabs
|
17
18
|
</div>
</div>
|
17f52abf
梁灏
update Tabs
|
19
20
21
22
23
24
|
</div>
</div>
</div>
</div>
<div :class="contentClasses" :style="contentStyle"><slot></slot></div>
</div>
|
871ed4d8
梁灏
init Tabs component
|
25
26
|
</template>
<script>
|
17f52abf
梁灏
update Tabs
|
27
|
import Icon from '../icon/icon.vue';
|
55dbf62d
Aresn
update Tabs render
|
28
|
import Render from '../base/render';
|
13261a8b
TabEnter
remove getStyle
|
29
|
import { oneOf } from '../../utils/assist';
|
67c9b1c8
梁灏
fixed #591
|
30
|
import Emitter from '../../mixins/emitter';
|
be3fbd24
marxy
Tabs add scroll
|
31
|
import elementResizeDetectorMaker from 'element-resize-detector';
|
17f52abf
梁灏
update Tabs
|
32
33
34
|
const prefixCls = 'ivu-tabs';
|
871ed4d8
梁灏
init Tabs component
|
35
|
export default {
|
30510c3d
梁灏
support Tabs
|
36
|
name: 'Tabs',
|
67c9b1c8
梁灏
fixed #591
|
37
|
mixins: [ Emitter ],
|
1f974700
Aresn
Tabs support rend...
|
38
|
components: { Icon, Render },
|
17f52abf
梁灏
update Tabs
|
39
|
props: {
|
30510c3d
梁灏
support Tabs
|
40
|
value: {
|
17f52abf
梁灏
update Tabs
|
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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
|
64
|
data () {
|
17f52abf
梁灏
update Tabs
|
65
66
67
68
|
return {
prefixCls: prefixCls,
navList: [],
barWidth: 0,
|
30510c3d
梁灏
support Tabs
|
69
|
barOffset: 0,
|
c4eb5dcf
H
tabs组件导航区添加右侧slot...
|
70
|
activeKey: this.value,
|
be3fbd24
marxy
Tabs add scroll
|
71
|
showSlot: false,
|
a730a849
梁灏
update Tabs
|
72
|
navStyle: {
|
be3fbd24
marxy
Tabs add scroll
|
73
74
|
transform: ''
},
|
a730a849
梁灏
update Tabs
|
75
|
scrollable: false
|
b0893113
jingsam
add eslint
|
76
|
};
|
17f52abf
梁灏
update Tabs
|
77
78
79
80
81
82
83
84
85
86
|
},
computed: {
classes () {
return [
`${prefixCls}`,
{
[`${prefixCls}-card`]: this.type === 'card',
[`${prefixCls}-mini`]: this.size === 'small' && this.type === 'line',
[`${prefixCls}-no-animation`]: !this.animated
}
|
b0893113
jingsam
add eslint
|
87
|
];
|
17f52abf
梁灏
update Tabs
|
88
89
90
91
|
},
contentClasses () {
return [
`${prefixCls}-content`,
|
77bafb31
梁灏
update Tabs
|
92
93
94
|
{
[`${prefixCls}-content-animated`]: this.animated
}
|
b0893113
jingsam
add eslint
|
95
|
];
|
17f52abf
梁灏
update Tabs
|
96
97
98
99
|
},
barClasses () {
return [
`${prefixCls}-ink-bar`,
|
77bafb31
梁灏
update Tabs
|
100
101
102
|
{
[`${prefixCls}-ink-bar-animated`]: this.animated
}
|
b0893113
jingsam
add eslint
|
103
|
];
|
17f52abf
梁灏
update Tabs
|
104
105
|
},
contentStyle () {
|
30510c3d
梁灏
support Tabs
|
106
|
const x = this.navList.findIndex((nav) => nav.name === this.activeKey);
|
17f52abf
梁灏
update Tabs
|
107
108
109
110
111
112
|
const p = x === 0 ? '0%' : `-${x}00%`;
let style = {};
if (x > -1) {
style = {
transform: `translateX(${p}) translateZ(0px)`
|
b0893113
jingsam
add eslint
|
113
|
};
|
17f52abf
梁灏
update Tabs
|
114
115
116
117
118
119
|
}
return style;
},
barStyle () {
let style = {
display: 'none',
|
77bafb31
梁灏
update Tabs
|
120
|
width: `${this.barWidth}px`
|
17f52abf
梁灏
update Tabs
|
121
122
|
};
if (this.type === 'line') style.display = 'block';
|
77bafb31
梁灏
update Tabs
|
123
124
125
126
127
|
if (this.animated) {
style.transform = `translate3d(${this.barOffset}px, 0px, 0px)`;
} else {
style.left = `${this.barOffset}px`;
}
|
17f52abf
梁灏
update Tabs
|
128
129
130
131
132
133
134
135
136
137
138
139
|
return style;
}
},
methods: {
getTabs () {
return this.$children.filter(item => item.$options.name === 'TabPane');
},
updateNav () {
this.navList = [];
this.getTabs().forEach((pane, index) => {
this.navList.push({
|
1f974700
Aresn
Tabs support rend...
|
140
|
labelType: typeof pane.label,
|
17f52abf
梁灏
update Tabs
|
141
142
|
label: pane.label,
icon: pane.icon || '',
|
30510c3d
梁灏
support Tabs
|
143
|
name: pane.currentName || index,
|
7a737482
梁灏
fixed #206
|
144
145
|
disabled: pane.disabled,
closable: pane.closable
|
17f52abf
梁灏
update Tabs
|
146
|
});
|
30510c3d
梁灏
support Tabs
|
147
|
if (!pane.currentName) pane.currentName = index;
|
17f52abf
梁灏
update Tabs
|
148
|
if (index === 0) {
|
30510c3d
梁灏
support Tabs
|
149
|
if (!this.activeKey) this.activeKey = pane.currentName || index;
|
17f52abf
梁灏
update Tabs
|
150
151
|
}
});
|
77bafb31
梁灏
update Tabs
|
152
|
this.updateStatus();
|
17f52abf
梁灏
update Tabs
|
153
154
155
156
|
this.updateBar();
},
updateBar () {
this.$nextTick(() => {
|
30510c3d
梁灏
support Tabs
|
157
158
|
const index = this.navList.findIndex((nav) => nav.name === this.activeKey);
const prevTabs = this.$refs.nav.querySelectorAll(`.${prefixCls}-tab`);
|
17f52abf
梁灏
update Tabs
|
159
|
const tab = prevTabs[index];
|
bdfab3b9
梁灏
fixed #1842
|
160
|
this.barWidth = tab ? parseFloat(tab.offsetWidth) : 0;
|
17f52abf
梁灏
update Tabs
|
161
162
163
164
165
|
if (index > 0) {
let offset = 0;
const gutter = this.size === 'small' ? 0 : 16;
for (let i = 0; i < index; i++) {
|
75798f5b
erhuluanzi
getComputedStyle在...
|
166
|
offset += parseFloat(prevTabs[i].offsetWidth) + gutter;
|
17f52abf
梁灏
update Tabs
|
167
168
169
170
171
172
|
}
this.barOffset = offset;
} else {
this.barOffset = 0;
}
|
be3fbd24
marxy
Tabs add scroll
|
173
|
this.updateNavScroll();
|
17f52abf
梁灏
update Tabs
|
174
175
|
});
},
|
77bafb31
梁灏
update Tabs
|
176
177
|
updateStatus () {
const tabs = this.getTabs();
|
30510c3d
梁灏
support Tabs
|
178
|
tabs.forEach(tab => tab.show = (tab.currentName === this.activeKey) || this.animated);
|
77bafb31
梁灏
update Tabs
|
179
|
},
|
17f52abf
梁灏
update Tabs
|
180
181
182
183
184
|
tabCls (item) {
return [
`${prefixCls}-tab`,
{
[`${prefixCls}-tab-disabled`]: item.disabled,
|
30510c3d
梁灏
support Tabs
|
185
|
[`${prefixCls}-tab-active`]: item.name === this.activeKey
|
17f52abf
梁灏
update Tabs
|
186
|
}
|
b0893113
jingsam
add eslint
|
187
|
];
|
17f52abf
梁灏
update Tabs
|
188
189
190
191
|
},
handleChange (index) {
const nav = this.navList[index];
if (nav.disabled) return;
|
30510c3d
梁灏
support Tabs
|
192
193
194
|
this.activeKey = nav.name;
this.$emit('input', nav.name);
this.$emit('on-click', nav.name);
|
17f52abf
梁灏
update Tabs
|
195
196
197
198
|
},
handleRemove (index) {
const tabs = this.getTabs();
const tab = tabs[index];
|
087ad37d
梁灏
update Tabs
|
199
|
tab.$destroy();
|
17f52abf
梁灏
update Tabs
|
200
|
|
30510c3d
梁灏
support Tabs
|
201
|
if (tab.currentName === this.activeKey) {
|
17f52abf
梁灏
update Tabs
|
202
203
204
205
206
207
208
209
|
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) {
|
30510c3d
梁灏
support Tabs
|
210
|
activeKey = rightNoDisabledTabs[0].currentName;
|
17f52abf
梁灏
update Tabs
|
211
|
} else if (leftNoDisabledTabs.length) {
|
30510c3d
梁灏
support Tabs
|
212
|
activeKey = leftNoDisabledTabs[leftNoDisabledTabs.length - 1].currentName;
|
17f52abf
梁灏
update Tabs
|
213
|
} else {
|
30510c3d
梁灏
support Tabs
|
214
|
activeKey = newTabs[0].currentName;
|
17f52abf
梁灏
update Tabs
|
215
216
217
|
}
}
this.activeKey = activeKey;
|
087ad37d
梁灏
update Tabs
|
218
|
this.$emit('input', activeKey);
|
17f52abf
梁灏
update Tabs
|
219
|
}
|
30510c3d
梁灏
support Tabs
|
220
|
this.$emit('on-tab-remove', tab.currentName);
|
17f52abf
梁灏
update Tabs
|
221
|
this.updateNav();
|
7a737482
梁灏
fixed #206
|
222
223
224
225
226
227
228
229
230
231
232
|
},
showClose (item) {
if (this.type === 'card') {
if (item.closable !== null) {
return item.closable;
} else {
return this.closable;
}
} else {
return false;
}
|
be3fbd24
marxy
Tabs add scroll
|
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
},
scrollPrev() {
const containerWidth = this.$refs.navScroll.offsetWidth;
const currentOffset = this.getCurrentScrollOffset();
if (!currentOffset) return;
let newOffset = currentOffset > containerWidth
? currentOffset - containerWidth
: 0;
this.setOffset(newOffset);
},
scrollNext() {
const navWidth = this.$refs.nav.offsetWidth;
const containerWidth = this.$refs.navScroll.offsetWidth;
const currentOffset = this.getCurrentScrollOffset();
if (navWidth - currentOffset <= containerWidth) return;
let newOffset = navWidth - currentOffset > containerWidth * 2
? currentOffset + containerWidth
: (navWidth - containerWidth);
this.setOffset(newOffset);
},
getCurrentScrollOffset() {
const { navStyle } = this;
return navStyle.transform
? Number(navStyle.transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1])
: 0;
},
setOffset(value) {
this.navStyle.transform = `translateX(-${value}px)`;
},
scrollToActiveTab() {
if (!this.scrollable) return;
const nav = this.$refs.nav;
const activeTab = this.$el.querySelector(`.${prefixCls}-tab-active`);
if(!activeTab) return;
const navScroll = this.$refs.navScroll;
const activeTabBounding = activeTab.getBoundingClientRect();
const navScrollBounding = navScroll.getBoundingClientRect();
const navBounding = nav.getBoundingClientRect();
const currentOffset = this.getCurrentScrollOffset();
let newOffset = currentOffset;
if (navBounding.right < navScrollBounding.right) {
newOffset = nav.offsetWidth - navScrollBounding.width;
}
if (activeTabBounding.left < navScrollBounding.left) {
newOffset = currentOffset - (navScrollBounding.left - activeTabBounding.left);
}else if (activeTabBounding.right > navScrollBounding.right) {
newOffset = currentOffset + activeTabBounding.right - navScrollBounding.right;
}
if(currentOffset !== newOffset){
this.setOffset(Math.max(newOffset, 0));
}
},
updateNavScroll(){
const navWidth = this.$refs.nav.offsetWidth;
const containerWidth = this.$refs.navScroll.offsetWidth;
const currentOffset = this.getCurrentScrollOffset();
if (containerWidth < navWidth) {
this.scrollable = true;
if (navWidth - currentOffset < containerWidth) {
this.setOffset(navWidth - containerWidth);
}
} else {
this.scrollable = false;
if (currentOffset > 0) {
this.setOffset(0);
}
}
},
handleResize(){
this.updateNavScroll();
|
17f52abf
梁灏
update Tabs
|
312
313
|
}
},
|
17f52abf
梁灏
update Tabs
|
314
|
watch: {
|
30510c3d
梁灏
support Tabs
|
315
316
317
|
value (val) {
this.activeKey = val;
},
|
17f52abf
梁灏
update Tabs
|
318
319
|
activeKey () {
this.updateBar();
|
0c5e01f1
梁灏
fixed #185
|
320
|
this.updateStatus();
|
67c9b1c8
梁灏
fixed #591
|
321
|
this.broadcast('Table', 'on-visible-change', true);
|
a730a849
梁灏
update Tabs
|
322
|
this.$nextTick(() => {
|
be3fbd24
marxy
Tabs add scroll
|
323
324
|
this.scrollToActiveTab();
});
|
17f52abf
梁灏
update Tabs
|
325
|
}
|
c4eb5dcf
H
tabs组件导航区添加右侧slot...
|
326
|
},
|
8e4f708f
梁灏
update Tabs
|
327
328
|
mounted () {
this.showSlot = this.$slots.extra !== undefined;
|
be3fbd24
marxy
Tabs add scroll
|
329
330
331
332
333
|
this.observer = elementResizeDetectorMaker();
this.observer.listenTo(this.$refs.navWrap, this.handleResize);
},
beforeDestroy() {
this.observer.removeListener(this.$refs.navWrap, this.handleResize);
|
17f52abf
梁灏
update Tabs
|
334
|
}
|
b0893113
jingsam
add eslint
|
335
336
|
};
</script>
|