Vue3中如何获取插槽内子组件的自身排列索引(以tabs组件为例)
不需要手动给每个tab组件传递索引类prop,以下是两种可直接落地的实现方案:
方案1:父组件主动遍历插槽赋值(适合静态tab场景)
tabs组件在渲染完成后,读取默认插槽的内容,过滤出所有tab组件实例,直接给每个实例赋值索引即可。tabs.vue新增逻辑:
export default { // 首次渲染完成后赋值索引 mounted() { this.updateTabIndex() }, // 插槽内容变化时更新索引,适配tab动态显示/隐藏的场景 updated() { this.updateTabIndex() }, methods: { updateTabIndex() { // 过滤默认插槽中所有tab组件的实例 const tabInstances = (this.$slots.default || []) .filter(vnode => vnode.componentInstance?.$options.name === 'Tab') .map(vnode => vnode.componentInstance) // 遍历赋值索引 tabInstances.forEach((tab, index) => tab.index = index) } } }
tab.vue中定义对应响应式属性即可直接使用:
export default { data() { return { // 初始值会被父组件自动覆盖 index: 0 } } }
方案2:provide/inject 注册机制(适合动态增减tab场景)
这是主流组件库的通用实现方案,支持动态新增/删除tab时自动更新所有索引。tabs.vue新增逻辑:
export default { // 给子组件暴露注册/注销方法 provide() { return { registerTab: this.registerTab, unregisterTab: this.unregisterTab } }, data() { return { // 维护所有已注册的tab实例列表 registeredTabs: [] } }, methods: { registerTab(tabInstance) { this.registeredTabs.push(tabInstance) // 重新计算所有tab的索引 this.refreshAllIndex() }, unregisterTab(tabInstance) { const removeIndex = this.registeredTabs.findIndex(tab => tab === tabInstance) if (removeIndex > -1) { this.registeredTabs.splice(removeIndex, 1) this.refreshAllIndex() } }, refreshAllIndex() { this.registeredTabs.forEach((tab, index) => tab.index = index) } } }
tab.vue新增逻辑,挂载时主动注册:
export default { // 注入父组件暴露的方法 inject: ['registerTab', 'unregisterTab'], data() { return { index: 0 } }, // 挂载时注册自身 mounted() { this.registerTab(this) }, // 销毁前注销自身 beforeUnmount() { this.unregisterTab(this) } }
两种方案都可以实现tab自动获取自身索引,无需使用者手动传递id,避免了手动输入错误的问题。
内容的提问来源于stack exchange,提问作者BT101
相关产品推荐
相关产品推荐

