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
|
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
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
312
|
},
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();
|
79885751
Kang Cheng
fix issue #1846
|
313
314
315
316
317
318
319
320
321
322
|
},
isInsideHiddenElement () {
let parentNode = this.$el.parentNode;
while(parentNode) {
if (parentNode.style.display === 'none') {
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
345
346
347
348
349
350
351
352
353
|
const hiddenParentNode = this.isInsideHiddenElement();
if (hiddenParentNode) {
const mutationObserver = new MutationObserver(() => {
if (hiddenParentNode.style.display !== 'none') {
this.updateBar();
mutationObserver.disconnect();
}
});
mutationObserver.observe(hiddenParentNode, { attributes: true, childList: true, characterData: true, attributeFilter: ['style'] });
}
|
be3fbd24
marxy
Tabs add scroll
|
354
355
356
|
},
beforeDestroy() {
this.observer.removeListener(this.$refs.navWrap, this.handleResize);
|
17f52abf
梁灏
update Tabs
|
357
|
}
|
b0893113
jingsam
add eslint
|
358
359
|
};
</script>
|