forked from zhurui/management
192 lines
4.6 KiB
Vue
192 lines
4.6 KiB
Vue
|
<script>
|
||
|
import TabNav from './tab-nav';
|
||
|
|
||
|
export default {
|
||
|
name: 'ElTabs',
|
||
|
|
||
|
components: {
|
||
|
TabNav
|
||
|
},
|
||
|
|
||
|
props: {
|
||
|
type: String,
|
||
|
activeName: String,
|
||
|
closable: Boolean,
|
||
|
addable: Boolean,
|
||
|
value: {},
|
||
|
editable: Boolean,
|
||
|
tabPosition: {
|
||
|
type: String,
|
||
|
default: 'top'
|
||
|
},
|
||
|
beforeLeave: Function,
|
||
|
stretch: Boolean
|
||
|
},
|
||
|
|
||
|
provide() {
|
||
|
return {
|
||
|
rootTabs: this
|
||
|
};
|
||
|
},
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
currentName: this.value || this.activeName,
|
||
|
panes: []
|
||
|
};
|
||
|
},
|
||
|
|
||
|
watch: {
|
||
|
activeName(value) {
|
||
|
this.setCurrentName(value);
|
||
|
},
|
||
|
value(value) {
|
||
|
this.setCurrentName(value);
|
||
|
},
|
||
|
currentName(value) {
|
||
|
if (this.$refs.nav) {
|
||
|
this.$nextTick(() => {
|
||
|
this.$refs.nav.$nextTick(_ => {
|
||
|
this.$refs.nav.scrollToActiveTab();
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
calcPaneInstances(isForceUpdate = false) {
|
||
|
if (this.$slots.default) {
|
||
|
const paneSlots = this.$slots.default.filter(vnode => vnode.tag &&
|
||
|
vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElTabPane');
|
||
|
// update indeed
|
||
|
const panes = paneSlots.map(({ componentInstance }) => componentInstance);
|
||
|
const panesChanged = !(panes.length === this.panes.length && panes.every((pane, index) => pane === this.panes[index]));
|
||
|
if (isForceUpdate || panesChanged) {
|
||
|
this.panes = panes;
|
||
|
}
|
||
|
} else if (this.panes.length !== 0) {
|
||
|
this.panes = [];
|
||
|
}
|
||
|
},
|
||
|
handleTabClick(tab, tabName, event) {
|
||
|
if (tab.disabled) return;
|
||
|
this.setCurrentName(tabName);
|
||
|
this.$emit('tab-click', tab, event);
|
||
|
},
|
||
|
handleTabRemove(pane, ev) {
|
||
|
if (pane.disabled) return;
|
||
|
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) {
|
||
|
const changeCurrentName = () => {
|
||
|
this.currentName = value;
|
||
|
this.$emit('input', value);
|
||
|
};
|
||
|
if (this.currentName !== value && this.beforeLeave) {
|
||
|
const before = this.beforeLeave(value, this.currentName);
|
||
|
if (before && before.then) {
|
||
|
before
|
||
|
.then(() => {
|
||
|
changeCurrentName();
|
||
|
this.$refs.nav && this.$refs.nav.removeFocus();
|
||
|
}, () => {
|
||
|
// https://github.com/ElemeFE/element/pull/14816
|
||
|
// ignore promise rejection in `before-leave` hook
|
||
|
});
|
||
|
} else if (before !== false) {
|
||
|
changeCurrentName();
|
||
|
}
|
||
|
} else {
|
||
|
changeCurrentName();
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
render(h) {
|
||
|
let {
|
||
|
type,
|
||
|
handleTabClick,
|
||
|
handleTabRemove,
|
||
|
handleTabAdd,
|
||
|
currentName,
|
||
|
panes,
|
||
|
editable,
|
||
|
addable,
|
||
|
tabPosition,
|
||
|
stretch
|
||
|
} = this;
|
||
|
|
||
|
const newButton = editable || addable
|
||
|
? (
|
||
|
<span
|
||
|
class="el-tabs__new-tab"
|
||
|
on-click={ handleTabAdd }
|
||
|
tabindex="0"
|
||
|
on-keydown={ (ev) => { if (ev.keyCode === 13) { handleTabAdd(); }} }
|
||
|
>
|
||
|
<i class="el-icon-plus"></i>
|
||
|
</span>
|
||
|
)
|
||
|
: null;
|
||
|
|
||
|
const navData = {
|
||
|
props: {
|
||
|
currentName,
|
||
|
onTabClick: handleTabClick,
|
||
|
onTabRemove: handleTabRemove,
|
||
|
editable,
|
||
|
type,
|
||
|
panes,
|
||
|
stretch
|
||
|
},
|
||
|
ref: 'nav'
|
||
|
};
|
||
|
const header = (
|
||
|
<div class={['el-tabs__header', `is-${tabPosition}`]}>
|
||
|
{newButton}
|
||
|
<tab-nav { ...navData }></tab-nav>
|
||
|
</div>
|
||
|
);
|
||
|
const panels = (
|
||
|
<div class="el-tabs__content">
|
||
|
{this.$slots.default}
|
||
|
</div>
|
||
|
);
|
||
|
|
||
|
return (
|
||
|
<div class={{
|
||
|
'el-tabs': true,
|
||
|
'el-tabs--card': type === 'card',
|
||
|
[`el-tabs--${tabPosition}`]: true,
|
||
|
'el-tabs--border-card': type === 'border-card'
|
||
|
}}>
|
||
|
{ tabPosition !== 'bottom' ? [header, panels] : [panels, header] }
|
||
|
</div>
|
||
|
);
|
||
|
},
|
||
|
|
||
|
created() {
|
||
|
if (!this.currentName) {
|
||
|
this.setCurrentName('0');
|
||
|
}
|
||
|
|
||
|
this.$on('tab-nav-update', this.calcPaneInstances.bind(null, true));
|
||
|
},
|
||
|
|
||
|
mounted() {
|
||
|
this.calcPaneInstances();
|
||
|
},
|
||
|
|
||
|
updated() {
|
||
|
this.calcPaneInstances();
|
||
|
}
|
||
|
};
|
||
|
</script>
|