VueJS问题:如何仅保留Component-B并移除插槽内其他HTML元素?
实现Component-A默认插槽仅渲染Component-B组件的方案
根据你的需求,只需在Component-A中对默认插槽的内容进行过滤,只保留Component-B类型的节点即可。下面分Vue 3和Vue 2两种常用版本给出具体实现:
Vue 3 实现方式
在Vue 3中可以通过useSlots获取插槽内容,过滤后仅保留ComponentB的VNode再渲染:
<!-- ComponentA.vue --> <template> <div class="component-a"> <!-- 遍历过滤后的插槽节点,动态渲染ComponentB --> <component v-for="(node, index) in filteredSlots" :key="index" :is="node.type" v-bind="node.props" v-on="node.props?.on" ></component> </div> </template> <script setup> import { useSlots } from 'vue' import ComponentB from './ComponentB.vue' const slots = useSlots() // 过滤默认插槽,仅保留ComponentB类型的节点 const filteredSlots = slots.default ? slots.default().filter(node => node.type === ComponentB) : [] </script>
说明
useSlots().default返回的是一个函数,执行后得到当前默认插槽的VNode数组- 通过判断VNode的
type是否等于ComponentB组件,过滤掉其他类型的元素 - 用
<component>动态渲染保留的节点,并传递原有的props和事件绑定
Vue 2 实现方式
Vue 2中通过this.$slots获取插槽,结合组件构造函数的name属性进行过滤:
<!-- ComponentA.vue --> <template> <div class="component-a"> <template v-for="(node, index) in filteredSlots" :key="index" > <component :is="node.componentOptions.Ctor" v-bind="node.data.attrs" v-on="node.data.on" ></component> </template> </div> </template> <script> import ComponentB from './ComponentB.vue' export default { computed: { filteredSlots() { const defaultSlots = this.$slots.default || [] // 过滤仅保留ComponentB节点,需确保ComponentB有name选项 return defaultSlots.filter(node => { return node.componentOptions && node.componentOptions.Ctor.options.name === ComponentB.name }) } } } </script>
说明
- Vue 2中
this.$slots.default直接是VNode数组 - 组件类型的VNode会包含
componentOptions属性,通过对比构造函数的name来匹配ComponentB(注意要给ComponentB显式声明name选项) - 同样用
<component>动态渲染过滤后的节点,传递原有属性和事件
注意事项
- 如果ComponentB是异步组件,建议用组件的
name属性进行判断(而非直接对比组件对象),避免因异步包装导致匹配失败 - 处理插槽为空的边界情况,防止出现数组遍历报错
- 上述实现会自动保留ComponentB内部的插槽内容,无需额外处理
内容的提问来源于stack exchange,提问作者NabiMo
相关产品推荐
相关产品推荐

