版本
-
"element-plus": "2.1.9"
Store
export interface Tab {
title: string
content: string
}
const store = createStore<{
tabs: Tab[]
current: Tab | null
}>({
state: {
tabs: [],
current: null
},
mutations: {
changeCurrent: (state, { index }) => {
state.current = state.tabs[index] || null
},
addTab: state => {
state.tabs.push({
title: `标签 - ${state.tabs.length + 1}`,
content: `内容 - ${state.tabs.length + 1}`
})
state.current = state.tabs[0]
},
removeTab: (state, { index }) => {
state.tabs.splice(index, 1)
}
}
})
页面
<template>
<el-input-number v-model="inputValue" />
<div>
{{ store.state.current?.title || '' }}
</div>
<el-button @click="() => addTab()">增加</el-button>
<el-tabs
v-model="state.name"
:closable="true"
type="border-card"
@tab-remove="tabPanelName => removeTab(tabPanelName.toString())"
>
<template v-for="(tab, index) in store.state.tabs" :key="index">
<el-tab-pane :label="tab.title" :name="`${index}`">
{{ tab.content }}
</el-tab-pane>
</template>
</el-tabs>
</template>
<script setup lang="ts">
import { computed, reactive, watch } from 'vue'
import { useStore } from 'vuex'
import { type Tab } from './store'
const store = useStore<{
tabs: Tab[]
current: Tab | null
}>()
const state = reactive<{
name: string
}>({
name: '0'
})
const addTab = () => {
store.commit('addTab')
}
const removeTab = (name: string) => {
const index = Number.parseInt(name)
store.commit('removeTab', { index })
const currentIndex = Number.parseInt(state.name)
if (index <= currentIndex) {
state.name = `${currentIndex - 1}`
}
}
watch(state, (newValue, oldValue) => {
store.commit('changeCurrent', { index: Number.parseInt(newValue.name) })
})
const inputValue = computed({
get: () => Number.parseInt(state.name),
set: value => (state.name = `${value}`)
})
</script>
坑点
el-tabs
组件的事件回调参数
tabPanelName
和
el-tab-pane
组件的参数
name
类型并不一致,需要额外进行转换。
如果直接使用数字类型的下标作为
name
,当切换到倒数第二个标签页并进行关闭时,
v-model
绑定的值会因为
0
和
"0"
类型不同,从而导致第一个 Tab 页无法自动显示。
版权声明:本文为XY1790026787原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。