Vue Slot失效问题:子组件显示为空数组
问题解决:Vue Tabs组件无法获取Slot中的Tab子组件
核心问题分析
- 钩子时机错误:
created钩子执行时,Slot中的Tab组件还未完成挂载,导致this.$children为空数组。 - 子组件获取方式不精准:
$children会包含所有子组件实例,无法保证只获取Tab组件,且依赖组件挂载顺序,稳定性差。
解决方案
1. 修改Tabs组件的逻辑
将子组件获取逻辑移到mounted钩子中,通过$slots.default精准筛选Tab组件实例:
<template> <article> <header class="tabs"> <ul> <li v-for="(tab, index) in tabs" :key="index"> <div class="nav-item" :class="{ 'is-active': tab.isActive }" @click="selectTab(tab)"> {{ tab.name }} </div> </li> </ul> </header> <section class="tabs-details"> <slot></slot> </section> </article> </template> <script> export default { data: () => ({ tabs: [] }), methods: { selectTab(selectedTab) { this.tabs.forEach(tab => { tab.isActive = tab.name === selectedTab.name; }); } }, mounted() { // 从默认Slot中筛选出Tab组件实例 this.tabs = this.$slots.default .filter(node => node.componentOptions?.tag === 'Tab') .map(node => node.componentInstance); // 初始化激活状态:优先选中标记selected="true"的Tab,否则选第一个 const activeTab = this.tabs.find(tab => tab.selected === 'true') || this.tabs[0]; if (activeTab) { this.selectTab(activeTab); } } } </script>
2. 完善Tab组件的Props定义
确保Tab组件接收name和selected属性,并维护isActive状态:
<template> <div v-show="isActive"> <slot></slot> </div> </template> <script> export default { props: ['name', 'selected'], data: () => ({ isActive: false }) } </script>
关键说明
mounted钩子是组件挂载完成后执行,此时Slot中的子组件已经实例化,能正确获取到Tab组件实例。$slots.default返回默认Slot中的所有节点,通过componentOptions.tag筛选出Tab组件,避免混入其他无关组件。- Tab组件中添加
v-show="isActive",实现切换时的内容显示/隐藏。
内容的提问来源于stack exchange,提问作者mikeym
相关产品推荐
相关产品推荐

