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']">
|
67a9c1cc
梁灏
update Tabs
|
6
|
<div ref="navWrap" :class="[prefixCls + '-nav-wrap', scrollable ? prefixCls + '-nav-scrollable' : '']">
|
be3fbd24
marxy
Tabs add scroll
|
7
8
9
10
|
<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';
|
3be0aa12
Kang Cheng
Import custom Mut...
|
29
|
import { oneOf, MutationObserver } 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
|
const index = this.navList.findIndex((nav) => nav.name === this.activeKey);
|
2993f4ee
梁灏
update Tab
|
158
|
if (!this.$refs.nav) return; // 页面销毁时,这里会报错,为了解决 #2100
|
30510c3d
梁灏
support Tabs
|
159
|
const prevTabs = this.$refs.nav.querySelectorAll(`.${prefixCls}-tab`);
|
17f52abf
梁灏
update Tabs
|
160
|
const tab = prevTabs[index];
|
bdfab3b9
梁灏
fixed #1842
|
161
|
this.barWidth = tab ? parseFloat(tab.offsetWidth) : 0;
|
17f52abf
梁灏
update Tabs
|
162
163
164
165
166
|
if (index > 0) {
let offset = 0;
const gutter = this.size === 'small' ? 0 : 16;
for (let i = 0; i < index; i++) {
|
75798f5b
erhuluanzi
getComputedStyle在...
|
167
|
offset += parseFloat(prevTabs[i].offsetWidth) + gutter;
|
17f52abf
梁灏
update Tabs
|
168
169
170
171
172
173
|
}
this.barOffset = offset;
} else {
this.barOffset = 0;
}
|
be3fbd24
marxy
Tabs add scroll
|
174
|
this.updateNavScroll();
|
17f52abf
梁灏
update Tabs
|
175
176
|
});
},
|
77bafb31
梁灏
update Tabs
|
177
178
|
updateStatus () {
const tabs = this.getTabs();
|
30510c3d
梁灏
support Tabs
|
179
|
tabs.forEach(tab => tab.show = (tab.currentName === this.activeKey) || this.animated);
|
77bafb31
梁灏
update Tabs
|
180
|
},
|
17f52abf
梁灏
update Tabs
|
181
182
183
184
185
|
tabCls (item) {
return [
`${prefixCls}-tab`,
{
[`${prefixCls}-tab-disabled`]: item.disabled,
|
30510c3d
梁灏
support Tabs
|
186
|
[`${prefixCls}-tab-active`]: item.name === this.activeKey
|
17f52abf
梁灏
update Tabs
|
187
|
}
|
b0893113
jingsam
add eslint
|
188
|
];
|
17f52abf
梁灏
update Tabs
|
189
190
191
192
|
},
handleChange (index) {
const nav = this.navList[index];
if (nav.disabled) return;
|
30510c3d
梁灏
support Tabs
|
193
194
195
|
this.activeKey = nav.name;
this.$emit('input', nav.name);
this.$emit('on-click', nav.name);
|
17f52abf
梁灏
update Tabs
|
196
197
198
199
|
},
handleRemove (index) {
const tabs = this.getTabs();
const tab = tabs[index];
|
087ad37d
梁灏
update Tabs
|
200
|
tab.$destroy();
|
17f52abf
梁灏
update Tabs
|
201
|
|
30510c3d
梁灏
support Tabs
|
202
|
if (tab.currentName === this.activeKey) {
|
17f52abf
梁灏
update Tabs
|
203
204
205
206
207
208
209
210
|
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
|
211
|
activeKey = rightNoDisabledTabs[0].currentName;
|
17f52abf
梁灏
update Tabs
|
212
|
} else if (leftNoDisabledTabs.length) {
|
30510c3d
梁灏
support Tabs
|
213
|
activeKey = leftNoDisabledTabs[leftNoDisabledTabs.length - 1].currentName;
|
17f52abf
梁灏
update Tabs
|
214
|
} else {
|
30510c3d
梁灏
support Tabs
|
215
|
activeKey = newTabs[0].currentName;
|
17f52abf
梁灏
update Tabs
|
216
217
218
|
}
}
this.activeKey = activeKey;
|
087ad37d
梁灏
update Tabs
|
219
|
this.$emit('input', activeKey);
|
17f52abf
梁灏
update Tabs
|
220
|
}
|
30510c3d
梁灏
support Tabs
|
221
|
this.$emit('on-tab-remove', tab.currentName);
|
17f52abf
梁灏
update Tabs
|
222
|
this.updateNav();
|
7a737482
梁灏
fixed #206
|
223
224
225
226
227
228
229
230
231
232
233
|
},
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
|
234
235
236
237
238
239
240
241
|
},
scrollPrev() {
const containerWidth = this.$refs.navScroll.offsetWidth;
const currentOffset = this.getCurrentScrollOffset();
if (!currentOffset) return;
let newOffset = currentOffset > containerWidth
|
a74be22e
Sergio Crisostomo
don't check DOM t...
|
242
243
|
? currentOffset - containerWidth
: 0;
|
be3fbd24
marxy
Tabs add scroll
|
244
245
246
247
248
249
250
251
252
253
|
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
|
a74be22e
Sergio Crisostomo
don't check DOM t...
|
254
255
|
? currentOffset + containerWidth
: (navWidth - containerWidth);
|
be3fbd24
marxy
Tabs add scroll
|
256
257
258
259
260
261
|
this.setOffset(newOffset);
},
getCurrentScrollOffset() {
const { navStyle } = this;
return navStyle.transform
|
a74be22e
Sergio Crisostomo
don't check DOM t...
|
262
263
|
? Number(navStyle.transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1])
: 0;
|
be3fbd24
marxy
Tabs add scroll
|
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
312
|
},
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();
|
79885751
Kang Cheng
fix issue #1846
|
313
314
315
|
},
isInsideHiddenElement () {
let parentNode = this.$el.parentNode;
|
a74be22e
Sergio Crisostomo
don't check DOM t...
|
316
|
while(parentNode && parentNode !== document.body) {
|
a90d1a20
yangdan8
解决isInsideHiddenE...
|
317
|
if (parentNode.style && parentNode.style.display === 'none') {
|
79885751
Kang Cheng
fix issue #1846
|
318
319
320
321
322
|
return parentNode;
}
parentNode = parentNode.parentNode;
}
return false;
|
17f52abf
梁灏
update Tabs
|
323
324
|
}
},
|
17f52abf
梁灏
update Tabs
|
325
|
watch: {
|
30510c3d
梁灏
support Tabs
|
326
327
328
|
value (val) {
this.activeKey = val;
},
|
17f52abf
梁灏
update Tabs
|
329
330
|
activeKey () {
this.updateBar();
|
0c5e01f1
梁灏
fixed #185
|
331
|
this.updateStatus();
|
67c9b1c8
梁灏
fixed #591
|
332
|
this.broadcast('Table', 'on-visible-change', true);
|
a730a849
梁灏
update Tabs
|
333
|
this.$nextTick(() => {
|
be3fbd24
marxy
Tabs add scroll
|
334
335
|
this.scrollToActiveTab();
});
|
17f52abf
梁灏
update Tabs
|
336
|
}
|
c4eb5dcf
H
tabs组件导航区添加右侧slot...
|
337
|
},
|
8e4f708f
梁灏
update Tabs
|
338
339
|
mounted () {
this.showSlot = this.$slots.extra !== undefined;
|
be3fbd24
marxy
Tabs add scroll
|
340
341
|
this.observer = elementResizeDetectorMaker();
this.observer.listenTo(this.$refs.navWrap, this.handleResize);
|
79885751
Kang Cheng
fix issue #1846
|
342
343
344
|
const hiddenParentNode = this.isInsideHiddenElement();
if (hiddenParentNode) {
|
3be0aa12
Kang Cheng
Import custom Mut...
|
345
|
this.mutationObserver = new MutationObserver(() => {
|
79885751
Kang Cheng
fix issue #1846
|
346
347
|
if (hiddenParentNode.style.display !== 'none') {
this.updateBar();
|
3be0aa12
Kang Cheng
Import custom Mut...
|
348
|
this.mutationObserver.disconnect();
|
79885751
Kang Cheng
fix issue #1846
|
349
350
351
|
}
});
|
3be0aa12
Kang Cheng
Import custom Mut...
|
352
|
this.mutationObserver.observe(hiddenParentNode, { attributes: true, childList: true, characterData: true, attributeFilter: ['style'] });
|
79885751
Kang Cheng
fix issue #1846
|
353
|
}
|
be3fbd24
marxy
Tabs add scroll
|
354
355
356
|
},
beforeDestroy() {
this.observer.removeListener(this.$refs.navWrap, this.handleResize);
|
9b6f316e
梁灏
fixed Tabs bug
|
357
|
if (this.mutationObserver) this.mutationObserver.disconnect();
|
17f52abf
梁灏
update Tabs
|
358
|
}
|
b0893113
jingsam
add eslint
|
359
360
|
};
</script>
|