You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js render函数是否允许复用插槽中已有的嵌套VNode?

核心问题说明

  • 你当前的代码功能完全正常,渲染出的真实DOM结构完全符合预期,devtools显示层级和DOM不一致是Vue插槽的固有机制导致的,不属于代码bug。
  • 普通插槽的VNode是在调用<row>的父组件中生成的,VNode的context、parent属性已经提前绑定了父组件和当前Row组件的实例。你把VNode传入b-col的children仅修改了DOM挂载位置,没有修改VNode本身的归属属性,而devtools是基于VNode归属属性展示组件树,因此会显示UiText是Row的直接子节点。
  • b-col的functional标记属于正常情况:BootstrapVue的b-col本身就是函数式组件,这类组件没有自身实例,性能更高,devtools会统一给函数式组件打上该标记。
  • 子组件的$parent确实是不可变的:UiText实例创建时$parent就固定为Row组件,b-col作为函数式组件没有实例,天然无法作为父组件被挂载到$parent链上,这是Vue的固定设计。
  • 你当前复用插槽VNode的做法本身是合法的,只要不同时把同一个VNode挂载到多个DOM节点上,就不会产生运行问题。

可选优化方案

如果需要devtools组件树和DOM结构完全对齐,可以将普通插槽改为作用域插槽实现:

  1. 调用Row组件时使用作用域插槽传递内容:
<row cols="4,8">
  <template #default>
    <ui-text name="A" />
    <ui-text name="B" />
  </template>
</row>
  1. 修改Row组件的render函数,调用作用域插槽生成新的VNode:
export default {
  props: ['cols'],
  computed: {
    columns() {
      let v = this.cols;
      if (!v) return [];
      return this.cols.split(/,/g);
    }
  },
  render: function(h) {
    let columns = this.columns;
    // 调用作用域插槽生成最新的VNode
    let children = this.$scopedSlots.default ? this.$scopedSlots.default() : [];
    let kids = [];
    for(let i = 0, s = Math.min(columns.length, children.length); i < s; i++) {
      let kid = children[i];
      kids.push(h('b-col', {props: {cols: columns[i]}}, [ kid ]));
    }
    return h('b-form-row', {}, kids);
  }
}

内容的提问来源于stack exchange,提问作者Daniel Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:54:02