update tab api

pull/2674/head
baiyaaaaa 2017-01-12 22:46:26 +08:00 committed by 杨奕
parent 14565178ed
commit 0bec05ada3
5 changed files with 619 additions and 179 deletions

View File

@ -2,9 +2,20 @@
export default { export default {
data() { data() {
return { return {
activeName: 'first', activeName: 'second',
activeName2: 'first', activeName2: 'first',
tabs: [{ editableTabsValue: '2',
editableTabsValue2: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
editableTabs2: [{
title: 'Tab 1', title: 'Tab 1',
name: '1', name: '1',
content: 'Tab 1 content' content: 'Tab 1 content'
@ -17,11 +28,62 @@
} }
}, },
methods: { methods: {
handleRemove(tab) {
console.log(tab);
},
handleClick(tab, event) { handleClick(tab, event) {
console.log(tab, event); console.log(tab, event);
},
handleTabsEdit(targetName, action) {
if (action === 'add') {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
}
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
},
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs2.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue2 = newTabName;
},
removeTab(targetName) {
let tabs = this.editableTabs2;
let activeName = this.editableTabsValue2;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue2 = activeName;
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
} }
} }
} }
@ -95,37 +157,6 @@ Tabs styled as cards.
``` ```
::: :::
### Closable
Closable tabs.
:::demo You can set the closable attribute in el-tabs to make all tabs closable. Also, closable can be set in a tab panel to make that specific tab closable.
```html
<template>
<el-tabs type="card" :closable="true" @tab-click="handleClick" @tab-remove="handleRemove">
<el-tab-pane label="User">User</el-tab-pane>
<el-tab-pane label="Config">Config</el-tab-pane>
<el-tab-pane label="Role">Role</el-tab-pane>
<el-tab-pane label="Task">Task</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
methods: {
handleRemove(tab) {
console.log(tab);
},
handleClick(tab, event) {
console.log(tab, event);
}
}
};
</script>
```
:::
### Border card ### Border card
Border card tabs. Border card tabs.
@ -161,11 +192,151 @@ You can use named slot to customize the tab label content.
``` ```
::: :::
### Add & close tab
Only card type Tabs support addable & closeable.
:::demo
```html
<el-tabs v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
<el-tab-pane
v-for="(item, index) in editableTabs"
:label="item.title"
:name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs>
<script>
export default {
data() {
return {
editableTabsValue: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
tabIndex: 2
}
},
methods: {
handleTabsEdit(targetName, action) {
if (action === 'add') {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
}
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
}
}
}
</script>
```
:::
### Customized trigger button of new tab
:::demo
```html
<div style="margin-bottom: 20px;">
<el-button
size="small"
@click="addTab(editableTabsValue2)"
>
add tab
</el-button>
</div>
<el-tabs v-model="editableTabsValue2" type="card" closable @tab-remove="removeTab">
<el-tab-pane
v-for="(item, index) in editableTabs2"
:label="item.title"
:name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs>
<script>
export default {
data() {
return {
editableTabsValue2: '2',
editableTabs2: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
tabIndex: 2
}
},
methods: {
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs2.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue2 = newTabName;
},
removeTab(targetName) {
let tabs = this.editableTabs2;
let activeName = this.editableTabsValue2;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue2 = activeName;
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
}
}
}
</script>
```
:::
### Tabs Attributes ### Tabs Attributes
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |
|---------- |-------- |---------- |------------- |-------- | |---------- |-------- |---------- |------------- |-------- |
| type | type of Tab | string | card/border-card | — | | type | type of Tab | string | card/border-card | — |
| closable | whether Tab is closable | boolean | — | false | | closable | whether Tab is closable | boolean | — | false |
| addable | whether Tab is addable | boolean | — | false |
| editable | whether Tab is addable and closable | boolean | — | false |
| active-name(deprecated) | name of the selected tab | string | — | name of first tab | | active-name(deprecated) | name of the selected tab | string | — | name of first tab |
| value | name of the selected tab | string | — | name of first tab | | value | name of the selected tab | string | — | name of first tab |
@ -173,7 +344,9 @@ You can use named slot to customize the tab label content.
| Event Name | Description | Parameters | | Event Name | Description | Parameters |
|---------- |-------- |---------- | |---------- |-------- |---------- |
| tab-click | triggers when a tab is clicked | clicked tab | | tab-click | triggers when a tab is clicked | clicked tab |
| tab-remove | triggers when a tab is removed | removed tab | | tab-remove | triggers when tab-remove button is clicked | name of the removed tab |
| tab-add | triggers when tab-add button is clicked | — |
| edit | triggers when tab-add button or tab-remove is clicked | (targetName, action) |
### Tab-pane Attributes ### Tab-pane Attributes
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |

View File

@ -4,7 +4,18 @@
return { return {
activeName: 'second', activeName: 'second',
activeName2: 'first', activeName2: 'first',
tabs: [{ editableTabsValue: '2',
editableTabsValue2: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
editableTabs2: [{
title: 'Tab 1', title: 'Tab 1',
name: '1', name: '1',
content: 'Tab 1 content' content: 'Tab 1 content'
@ -17,11 +28,62 @@
} }
}, },
methods: { methods: {
handleRemove(tab) {
console.log(tab);
},
handleClick(tab, event) { handleClick(tab, event) {
console.log(tab, event); console.log(tab, event);
},
handleTabsEdit(targetName, action) {
if (action === 'add') {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
}
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
},
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs2.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue2 = newTabName;
},
removeTab(targetName) {
let tabs = this.editableTabs2;
let activeName = this.editableTabsValue2;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue2 = activeName;
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
} }
} }
} }
@ -95,36 +157,6 @@
``` ```
::: :::
### 可关闭
可以关闭标签页。
:::demo 通过设置 `closable` 属性来打开 `Tabs` 的可关闭标签效果, `closable` 也可以设置在 `Tab Panel` 中实现部分标签页的可关闭效果。
```html
<template>
<el-tabs type="card" closable @tab-click="handleClick" @tab-remove="handleRemove">
<el-tab-pane label="用户管理">用户管理</el-tab-pane>
<el-tab-pane label="配置管理">配置管理</el-tab-pane>
<el-tab-pane label="角色管理">角色管理</el-tab-pane>
<el-tab-pane label="定时任务补偿">定时任务补偿</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
methods: {
handleRemove(tab) {
console.log(tab);
},
handleClick(tab, event) {
console.log(tab, event);
}
}
};
</script>
```
:::
### 卡片化 ### 卡片化
卡片化的标签页。 卡片化的标签页。
@ -158,18 +190,141 @@
``` ```
::: :::
### 动态增标签页 ### 动态增标签页
展示如何通过触发器来动态增加标签页 增减标签页按钮只能在选项卡样式的标签页下使用
:::demo
```html
<el-tabs v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
<el-tab-pane
v-for="(item, index) in editableTabs"
:label="item.title"
:name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs>
<script>
export default {
data() {
return {
editableTabsValue: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
tabIndex: 2
}
},
methods: {
handleTabsEdit(targetName, action) {
if (action === 'add') {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
}
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
}
}
}
</script>
```
:::
### 自定义增加标签页触发器
:::demo :::demo
```html ```html
<div style="margin-bottom: 20px;"> <div style="margin-bottom: 20px;">
<el-button size="small" @click="tabs.push({ name: 'Tab ' + ++tabIndex, title: 'new Tab', content: 'new Tab content' })">add tab</el-button> <el-button
size="small"
@click="addTab(editableTabsValue2)"
>
add tab
</el-button>
</div> </div>
<el-tabs type="card" closable> <el-tabs v-model="editableTabsValue2" type="card" closable @tab-remove="removeTab">
<el-tab-pane v-for="(item, index) in tabs" :label="item.title" :name="item.name">{{item.content}}</el-tab-pane> <el-tab-pane
v-for="(item, index) in editableTabs2"
:label="item.title"
:name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs> </el-tabs>
<script>
export default {
data() {
return {
editableTabsValue2: '2',
editableTabs2: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
tabIndex: 2
}
},
methods: {
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs2.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue2 = newTabName;
},
removeTab(targetName) {
let tabs = this.editableTabs2;
let activeName = this.editableTabsValue2;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue2 = activeName;
this.editableTabs2 = tabs.filter(tab => tab.name !== targetName);
}
}
}
</script>
``` ```
::: :::
@ -178,14 +333,18 @@
|---------- |-------- |---------- |------------- |-------- | |---------- |-------- |---------- |------------- |-------- |
| type | 风格类型 | string | card/border-card | — | | type | 风格类型 | string | card/border-card | — |
| closable | 标签是否可关闭 | boolean | — | false | | closable | 标签是否可关闭 | boolean | — | false |
| addable | 标签是否可增加 | boolean | — | false |
| editable | 标签是否同时可增加和关闭 | boolean | — | false |
| active-name(deprecated) | 选中选项卡的 name | string | — | 第一个选项卡的 name | | active-name(deprecated) | 选中选项卡的 name | string | — | 第一个选项卡的 name |
| value | 绑定值,选中选项卡的 name | string | — | 第一个选项卡的 name | | value | 绑定值,选中选项卡的 name | string | — | 第一个选项卡的 name |
### Tabs Events ### Tabs Events
| 事件名称 | 说明 | 回调参数 | | 事件名称 | 说明 | 回调参数 |
|---------- |-------- |---------- | |---------- |-------- |---------- |
| tab-click | tab 被选中的钩子 | 被选中的标签 tab 实例 | | tab-click | tab 被选中时触发 | 被选中的标签 tab 实例 |
| tab-remove | tab 被删除的钩子 | 被删除的标签 tab 实例 | | tab-remove | 点击 tab 移除按钮后触发 | 被删除的标签的 name |
| tab-add | 点击 tabs 的新增按钮后触发 | — |
| edit | 点击 tabs 的新增按钮或 tab 被关闭后触发 | (targetName, action) |
### Tab-pane Attributes ### Tab-pane Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -10,11 +10,10 @@
props: { props: {
type: String, type: String,
activeName: String, activeName: String,
closable: { closable: Boolean,
type: Boolean, addable: Boolean,
default: false value: {},
}, editable: Boolean
value: {}
}, },
data() { data() {
@ -34,54 +33,21 @@
} }
}, },
computed: {
currentTab() {
let result;
this.panes.forEach(tab => {
if (this.currentName === (tab.name || tab.index)) {
result = tab;
}
});
return result;
}
},
methods: { methods: {
handleTabRemove(pane, event) {
event.stopPropagation();
const panes = this.panes;
const currentTab = this.currentTab;
let index = panes.indexOf(pane);
if (index === -1) return;
panes.splice(index, 1);
pane.$destroy();
this.$emit('tab-remove', pane);
this.$nextTick(_ => {
if (pane.active) {
const panes = this.panes;
let nextChild = panes[index];
let prevChild = panes[index - 1];
let nextActiveTab = nextChild || prevChild || null;
if (nextActiveTab) {
this.setCurrentName(nextActiveTab.name || nextActiveTab.index);
}
return;
} else {
this.setCurrentName(currentTab.name || currentTab.index);
}
});
},
handleTabClick(tab, tabName, event) { handleTabClick(tab, tabName, event) {
if (tab.disabled) return; if (tab.disabled) return;
this.setCurrentName(tabName); this.setCurrentName(tabName);
this.$emit('tab-click', tab, event); this.$emit('tab-click', tab, event);
}, },
handleTabRemove(pane, ev) {
ev.stopPropagation();
this.$emit('edit', pane.name, 'remove');
this.$emit('tab-remove', pane.name);
},
handleTabAdd() {
this.$emit('edit', null, 'add');
this.$emit('tab-add');
},
setCurrentName(value) { setCurrentName(value) {
this.currentName = value; this.currentName = value;
this.$emit('input', value); this.$emit('input', value);
@ -100,21 +66,37 @@
render(h) { render(h) {
let { let {
type, type,
handleTabRemove,
handleTabClick, handleTabClick,
handleTabRemove,
handleTabAdd,
currentName, currentName,
panes panes,
editable,
addable
} = this; } = this;
const newButton = editable || addable
? (
<span
class="el-tabs__new-button"
on-click={ handleTabAdd }
>
<i class="el-icon-plus"></i>
</span>
)
: null;
const tabs = this._l(panes, (pane, index) => { const tabs = this._l(panes, (pane, index) => {
let tabName = pane.name || pane.index || index; let tabName = pane.name || pane.index || index;
const closable = pane.isClosable || editable;
if (currentName === undefined && index === 0) { if (currentName === undefined && index === 0) {
this.setCurrentName(tabName); this.setCurrentName(tabName);
} }
pane.index = index; pane.index = index;
const btnClose = pane.isClosable const btnClose = closable
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(pane, ev); }}></span> ? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(pane, ev); }}></span>
: null; : null;
@ -125,7 +107,7 @@
'el-tabs__item': true, 'el-tabs__item': true,
'is-active': pane.active, 'is-active': pane.active,
'is-disabled': pane.disabled, 'is-disabled': pane.disabled,
'is-closable': pane.isClosable 'is-closable': closable
}} }}
ref="tabs" ref="tabs"
refInFor refInFor
@ -146,6 +128,7 @@
<div class="el-tabs__header"> <div class="el-tabs__header">
{!type ? <tab-bar tabs={panes}></tab-bar> : null} {!type ? <tab-bar tabs={panes}></tab-bar> : null}
{tabs} {tabs}
{newButton}
</div> </div>
<div class="el-tabs__content"> <div class="el-tabs__content">
{this.$slots.default} {this.$slots.default}

View File

@ -20,6 +20,28 @@
transition: transform .3s cubic-bezier(.645,.045,.355,1); transition: transform .3s cubic-bezier(.645,.045,.355,1);
list-style: none; list-style: none;
} }
@e new-button {
float: left;
border: 1px solid #d3dce6;
height: 18px;
width: @height;
line-height: @height;
margin: 12px 0 9px 10px;
border-radius: 3px;
text-align: center;
font-size: 12px;
color: #d3dce6;
cursor: pointer;
transition: all .15s;
.el-icon-plus {
transform: scale(0.8, 0.8);
}
&:hover {
color: var(--color-primary);
}
}
@e item { @e item {
padding: 0 16px; padding: 0 16px;
height: 42px; height: 42px;

View File

@ -140,33 +140,172 @@ describe('Tabs', () => {
}); });
}, 100); }, 100);
}); });
it('closable', done => { it('editable', done => {
vm = createVue({ vm = createVue({
template: ` template: `
<el-tabs type="card" :closable="true" ref="tabs"> <el-tabs ref="tabs" v-model="editableTabsValue" type="card" editable @edit="handleTabsEdit">
<el-tab-pane label="用户管理">A</el-tab-pane> <el-tab-pane
<el-tab-pane label="配置管理">B</el-tab-pane> v-for="(item, index) in editableTabs"
<el-tab-pane label="角色管理">C</el-tab-pane> :label="item.title"
<el-tab-pane label="定时任务补偿">D</el-tab-pane> :name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs> </el-tabs>
` `,
data() {
return {
editableTabsValue: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}, {
title: 'Tab 3',
name: '3',
content: 'Tab 3 content'
}],
tabIndex: 3
};
},
methods: {
handleTabsEdit(targetName, action) {
if (action === 'add') {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
}
if (action === 'remove') {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
}
}
}, true); }, true);
let spy = sinon.spy();
vm.$refs.tabs.$on('tab-remove', spy);
setTimeout(_ => { setTimeout(_ => {
const tabList = vm.$refs.tabs.$refs.tabs; const tabList = vm.$refs.tabs.$refs.tabs;
const paneList = vm.$el.querySelector('.el-tabs__content').children; const paneList = vm.$el.querySelector('.el-tabs__content').children;
tabList[1].querySelector('.el-icon-close').click(); tabList[1].querySelector('.el-icon-close').click();
vm.$nextTick(_ => {
expect(tabList.length).to.be.equal(2);
expect(paneList.length).to.be.equal(2);
expect(tabList[1].classList.contains('is-active')).to.be.true;
vm.$refs.tabs.$el.querySelector('.el-tabs__new-button').click();
vm.$nextTick(_ => {
expect(tabList.length).to.be.equal(3);
expect(paneList.length).to.be.equal(3);
expect(tabList[2].classList.contains('is-active')).to.be.true;
done();
});
});
}, 100);
});
it('addable & closable', done => {
vm = createVue({
template: `
<el-tabs
ref="tabs"
v-model="editableTabsValue"
type="card"
addable
closable
@tab-add="addTab"
@tab-remove="removeTab"
>
<el-tab-pane
v-for="(item, index) in editableTabs"
:label="item.title"
:name="item.name"
>
{{item.content}}
</el-tab-pane>
</el-tabs>
`,
data() {
return {
editableTabsValue: '2',
editableTabs: [{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content'
}, {
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
}],
tabIndex: 2
};
},
methods: {
addTab(targetName) {
let newTabName = ++this.tabIndex + '';
this.editableTabs.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content'
});
this.editableTabsValue = newTabName;
},
removeTab(targetName) {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
}
}
}, true);
setTimeout(_ => {
const tabList = vm.$refs.tabs.$refs.tabs;
const paneList = vm.$el.querySelector('.el-tabs__content').children;
vm.$refs.tabs.$el.querySelector('.el-tabs__new-button').click();
vm.$nextTick(_ => { vm.$nextTick(_ => {
expect(tabList.length).to.be.equal(3); expect(tabList.length).to.be.equal(3);
expect(paneList.length).to.be.equal(3); expect(paneList.length).to.be.equal(3);
expect(spy.calledOnce).to.true; expect(tabList[2].classList.contains('is-active')).to.be.true;
expect(tabList[1].innerText.trim()).to.be.equal('角色管理');
expect(paneList[0].innerText.trim()).to.be.equal('A'); tabList[2].querySelector('.el-icon-close').click();
done(); vm.$nextTick(_ => {
expect(tabList.length).to.be.equal(2);
expect(paneList.length).to.be.equal(2);
expect(tabList[1].classList.contains('is-active')).to.be.true;
done();
});
}); });
}, 100); }, 100);
}); });
@ -187,42 +326,6 @@ describe('Tabs', () => {
done(); done();
}, 100); }, 100);
}); });
it('closable edge', done => {
vm = createVue({
template: `
<el-tabs type="card" :closable="true" ref="tabs">
<el-tab-pane label="用户管理">A</el-tab-pane>
<el-tab-pane label="配置管理">B</el-tab-pane>
<el-tab-pane label="角色管理">C</el-tab-pane>
<el-tab-pane label="定时任务补偿">D</el-tab-pane>
</el-tabs>
`
}, true);
vm.$nextTick(_ => {
const paneList = vm.$el.querySelector('.el-tabs__content').children;
const tabList = vm.$refs.tabs.$refs.tabs;
tabList[0].querySelector('.el-icon-close').click();
vm.$nextTick(_ => {
expect(tabList.length).to.be.equal(3);
expect(paneList.length).to.be.equal(3);
expect(tabList[0].innerText.trim()).to.be.equal('配置管理');
expect(paneList[0].innerText.trim()).to.be.equal('B');
tabList[2].click();
tabList[2].querySelector('.el-icon-close').click();
setTimeout(_ => {
expect(tabList.length).to.be.equal(2);
expect(paneList.length).to.be.equal(2);
expect(tabList[1].classList.contains('is-active')).to.be.true;
expect(tabList[1].innerText.trim()).to.be.equal('角色管理');
expect(paneList[1].innerText.trim()).to.be.equal('C');
done();
}, 100);
});
});
});
it('disabled', done => { it('disabled', done => {
vm = createVue({ vm = createVue({
template: ` template: `