mirror of https://github.com/ElemeFE/element
fix tab-bar initial status bug
parent
7562e82bf6
commit
0c0f2527e3
|
@ -2,7 +2,7 @@
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeName: 'first',
|
activeName: 'second',
|
||||||
activeName2: 'first',
|
activeName2: 'first',
|
||||||
tabs: [{
|
tabs: [{
|
||||||
title: 'Tab 1',
|
title: 'Tab 1',
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeName: 'first'
|
activeName: 'second'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<div class="el-tabs__active-bar" :style="barStyle"></div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
tabs: Array
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
barStyle: {
|
||||||
|
cache: false,
|
||||||
|
get() {
|
||||||
|
if (!this.$parent.$refs.tabs) return {};
|
||||||
|
let style = {};
|
||||||
|
let offset = 0;
|
||||||
|
let tabWidth = 0;
|
||||||
|
|
||||||
|
this.tabs.every((tab, index) => {
|
||||||
|
let $el = this.$parent.$refs.tabs[index];
|
||||||
|
if (!$el) { return false; }
|
||||||
|
|
||||||
|
if (!tab.active) {
|
||||||
|
offset += $el.clientWidth;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
tabWidth = $el.clientWidth;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
style.width = tabWidth + 'px';
|
||||||
|
style.transform = `translateX(${offset}px)`;
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -9,6 +9,8 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ElTabPane',
|
name: 'ElTabPane',
|
||||||
|
|
||||||
|
componentName: 'ElTabPane',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
label: String,
|
label: String,
|
||||||
labelContent: Function,
|
labelContent: Function,
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
|
import TabBar from './tab-bar';
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ElTabs',
|
name: 'ElTabs',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
TabBar
|
||||||
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
type: String,
|
type: String,
|
||||||
activeName: String,
|
activeName: String,
|
||||||
|
@ -29,10 +34,16 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
tabPanes: {
|
||||||
|
cache: false,
|
||||||
|
get() {
|
||||||
|
if (!this.$children) return [];
|
||||||
|
return this.$children.filter(item => item.$options.componentName === 'ElTabPane');
|
||||||
|
}
|
||||||
|
},
|
||||||
currentTab() {
|
currentTab() {
|
||||||
if (!this.$children) return;
|
|
||||||
let result;
|
let result;
|
||||||
this.$children.forEach(tab => {
|
this.tabPanes.forEach(tab => {
|
||||||
if (this.currentName === (tab.name || tab.index)) {
|
if (this.currentName === (tab.name || tab.index)) {
|
||||||
result = tab;
|
result = tab;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +55,7 @@
|
||||||
methods: {
|
methods: {
|
||||||
handleTabRemove(tab, event) {
|
handleTabRemove(tab, event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const tabs = this.$children;
|
const tabs = this.tabPanes;
|
||||||
const currentTab = this.currentTab;
|
const currentTab = this.currentTab;
|
||||||
|
|
||||||
let index = tabs.indexOf(tab);
|
let index = tabs.indexOf(tab);
|
||||||
|
@ -55,6 +66,7 @@
|
||||||
|
|
||||||
this.$nextTick(_ => {
|
this.$nextTick(_ => {
|
||||||
if (tab.active) {
|
if (tab.active) {
|
||||||
|
const tabs = this.tabPanes;
|
||||||
let nextChild = tabs[index];
|
let nextChild = tabs[index];
|
||||||
let prevChild = tabs[index - 1];
|
let prevChild = tabs[index - 1];
|
||||||
let nextActiveTab = nextChild || prevChild || null;
|
let nextActiveTab = nextChild || prevChild || null;
|
||||||
|
@ -86,35 +98,11 @@
|
||||||
type,
|
type,
|
||||||
handleTabRemove,
|
handleTabRemove,
|
||||||
handleTabClick,
|
handleTabClick,
|
||||||
currentName
|
currentName,
|
||||||
|
tabPanes
|
||||||
} = this;
|
} = this;
|
||||||
|
|
||||||
const getBarStyle = () => {
|
const tabs = this._l(tabPanes, (tab, index) => {
|
||||||
if (this.type || !this.$refs.tabs) return {};
|
|
||||||
let style = {};
|
|
||||||
let offset = 0;
|
|
||||||
let tabWidth = 0;
|
|
||||||
|
|
||||||
this.$children.every((tab, index) => {
|
|
||||||
let $el = this.$refs.tabs[index];
|
|
||||||
if (!$el) { return false; }
|
|
||||||
|
|
||||||
if (!tab.active) {
|
|
||||||
offset += $el.clientWidth;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
tabWidth = $el.clientWidth;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
style.width = tabWidth + 'px';
|
|
||||||
style.transform = `translateX(${offset}px)`;
|
|
||||||
|
|
||||||
return style;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tabs = this.$children.map((tab, index) => {
|
|
||||||
let tabName = tab.name || tab.index || index;
|
let tabName = tab.name || tab.index || index;
|
||||||
if (currentName === undefined && index === 0) {
|
if (currentName === undefined && index === 0) {
|
||||||
this.setCurrentName(tabName);
|
this.setCurrentName(tabName);
|
||||||
|
@ -122,16 +110,11 @@
|
||||||
|
|
||||||
tab.index = index;
|
tab.index = index;
|
||||||
|
|
||||||
const activeBar = !type && index === 0
|
|
||||||
? <div class="el-tabs__active-bar" style={getBarStyle()}></div>
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const btnClose = tab.isClosable
|
const btnClose = tab.isClosable
|
||||||
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(tab, ev); }}></span>
|
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(tab, ev); }}></span>
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const tabLabelContent = tab.$slots.label || tab.label;
|
const tabLabelContent = tab.$slots.label || tab.label;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
|
@ -146,10 +129,10 @@
|
||||||
>
|
>
|
||||||
{tabLabelContent}
|
{tabLabelContent}
|
||||||
{btnClose}
|
{btnClose}
|
||||||
{activeBar}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={{
|
<div class={{
|
||||||
'el-tabs': true,
|
'el-tabs': true,
|
||||||
|
@ -157,6 +140,7 @@
|
||||||
'el-tabs--border-card': type === 'border-card'
|
'el-tabs--border-card': type === 'border-card'
|
||||||
}}>
|
}}>
|
||||||
<div class="el-tabs__header">
|
<div class="el-tabs__header">
|
||||||
|
{!type ? <tab-bar tabs={tabPanes}></tab-bar> : null}
|
||||||
{tabs}
|
{tabs}
|
||||||
</div>
|
</div>
|
||||||
<div class="el-tabs__content">
|
<div class="el-tabs__content">
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background-color: var(--color-primary);
|
background-color: var(--color-primary);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
|
@ -17,13 +17,14 @@ describe('Tabs', () => {
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
`
|
`
|
||||||
}, true);
|
}, true);
|
||||||
let tabList = vm.$el.querySelector('.el-tabs__header').children;
|
|
||||||
let paneList = vm.$el.querySelector('.el-tabs__content').children;
|
let paneList = vm.$el.querySelector('.el-tabs__content').children;
|
||||||
let spy = sinon.spy();
|
let spy = sinon.spy();
|
||||||
|
|
||||||
vm.$refs.tabs.$on('tab-click', spy);
|
vm.$refs.tabs.$on('tab-click', spy);
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
|
const tabList = vm.$refs.tabs.$refs.tabs;
|
||||||
expect(tabList[0].classList.contains('is-active')).to.be.true;
|
expect(tabList[0].classList.contains('is-active')).to.be.true;
|
||||||
expect(paneList[0].style.display).to.not.ok;
|
expect(paneList[0].style.display).to.not.ok;
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ describe('Tabs', () => {
|
||||||
it('active-name', done => {
|
it('active-name', done => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-tabs :active-name="activeName" @click="handleClick">
|
<el-tabs ref="tabs" :active-name="activeName" @click="handleClick">
|
||||||
<el-tab-pane name="tab-A" label="用户管理">A</el-tab-pane>
|
<el-tab-pane name="tab-A" label="用户管理">A</el-tab-pane>
|
||||||
<el-tab-pane name="tab-B" label="配置管理">B</el-tab-pane>
|
<el-tab-pane name="tab-B" label="配置管理">B</el-tab-pane>
|
||||||
<el-tab-pane name="tab-C" label="角色管理">C</el-tab-pane>
|
<el-tab-pane name="tab-C" label="角色管理">C</el-tab-pane>
|
||||||
|
@ -57,10 +58,12 @@ describe('Tabs', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
let tabList = vm.$el.querySelector('.el-tabs__header').children;
|
|
||||||
let paneList = vm.$el.querySelector('.el-tabs__content').children;
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
|
const paneList = vm.$el.querySelector('.el-tabs__content').children;
|
||||||
|
const tabList = vm.$refs.tabs.$refs.tabs;
|
||||||
|
|
||||||
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
expect(tabList[1].classList.contains('is-active')).to.be.true;
|
||||||
|
// expect(vm.$el.querySelector('.el-tabs__active-bar'))
|
||||||
expect(paneList[1].style.display).to.not.ok;
|
expect(paneList[1].style.display).to.not.ok;
|
||||||
|
|
||||||
tabList[3].click();
|
tabList[3].click();
|
||||||
|
@ -150,13 +153,13 @@ describe('Tabs', () => {
|
||||||
`
|
`
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
let tabList = vm.$el.querySelector('.el-tabs__header').children;
|
|
||||||
let paneList = vm.$el.querySelector('.el-tabs__content').children;
|
|
||||||
let spy = sinon.spy();
|
let spy = sinon.spy();
|
||||||
|
|
||||||
vm.$refs.tabs.$on('tab-remove', spy);
|
vm.$refs.tabs.$on('tab-remove', spy);
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
|
const tabList = vm.$refs.tabs.$refs.tabs;
|
||||||
|
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(_ => {
|
vm.$nextTick(_ => {
|
||||||
expect(tabList.length).to.be.equal(3);
|
expect(tabList.length).to.be.equal(3);
|
||||||
|
@ -197,9 +200,10 @@ describe('Tabs', () => {
|
||||||
`
|
`
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
let tabList = vm.$el.querySelector('.el-tabs__header').children;
|
|
||||||
let paneList = vm.$el.querySelector('.el-tabs__content').children;
|
|
||||||
vm.$nextTick(_ => {
|
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();
|
tabList[0].querySelector('.el-icon-close').click();
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
expect(tabList.length).to.be.equal(3);
|
expect(tabList.length).to.be.equal(3);
|
||||||
|
@ -223,7 +227,7 @@ describe('Tabs', () => {
|
||||||
it('disabled', done => {
|
it('disabled', done => {
|
||||||
vm = createVue({
|
vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-tabs type="card">
|
<el-tabs type="card" ref="tabs">
|
||||||
<el-tab-pane label="用户管理">A</el-tab-pane>
|
<el-tab-pane label="用户管理">A</el-tab-pane>
|
||||||
<el-tab-pane disabled label="配置管理" ref="disabled">B</el-tab-pane>
|
<el-tab-pane disabled label="配置管理" ref="disabled">B</el-tab-pane>
|
||||||
<el-tab-pane label="角色管理">C</el-tab-pane>
|
<el-tab-pane label="角色管理">C</el-tab-pane>
|
||||||
|
@ -233,7 +237,7 @@ describe('Tabs', () => {
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
let tabList = vm.$el.querySelector('.el-tabs__header').children;
|
const tabList = vm.$refs.tabs.$refs.tabs;
|
||||||
|
|
||||||
tabList[1].click();
|
tabList[1].click();
|
||||||
vm.$nextTick(_ => {
|
vm.$nextTick(_ => {
|
||||||
|
|
Loading…
Reference in New Issue