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

如何在Vue模板中使用VNode并解决循环结构转JSON报错问题

错误原因

  1. 你在qf-dialog的created钩子中执行了JSON.parse(JSON.stringify(this.content)),传入的content是Vue组件对象,本身包含_renderProxy这类存在循环引用的内部属性,JSON序列化时会直接抛出你遇到的循环结构转换错误,这行代码完全是多余操作。
  2. 模板的双大括号{{}}属于文本插值,只能输出文本内容,无法渲染VNode,就算你生成了合法的VNode,用双大括号也只会输出它的字符串形式,无法渲染成真实DOM。
  3. 你没有在qf-dialog的props中声明content属性,传入的content会被归到$attrs中,无法通过this.content稳定获取。

修复方案

方案1:使用动态组件(最简实现)

直接用Vue内置的<component>动态组件渲染传入的组件,不需要手动创建VNode,修改qf-dialog代码如下:

<template>
  <el-dialog :visible.sync="visible" v-bind="$attrs" v-on="$listeners">
    <!-- 动态渲染传入的组件,同时支持绑定自定义props -->
    <component :is="content" v-bind="contentProps" v-on="contentListeners" />
  </el-dialog>
</template>

<script>
export default {
  name: 'qf-dialog',
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    // 声明接收传入的组件
    content: {
      type: [Object, Function],
      required: true
    },
    // 可选:给传入的组件传递props
    contentProps: {
      type: Object,
      default: () => ({})
    },
    // 可选:监听传入组件的自定义事件
    contentListeners: {
      type: Object,
      default: () => ({})
    }
  }
};
</script>

调用时如果需要给demo组件传参,可以按如下方式写:

import demo from './demo.vue';

methods: {
  open() {
    const dialog = this.$dialog({
      content: demo,
      contentProps: {
        id: 1,
        title: '测试内容'
      },
      contentListeners: {
        'submit': (val) => {
          console.log('接收demo组件抛出的submit事件', val)
        }
      }
    });
  }
}

方案2:手动创建VNode(自定义渲染逻辑时使用)

如果你需要自己控制VNode的生成逻辑,可以用render函数替代模板实现,修改qf-dialog代码如下:

<script>
export default {
  name: 'qf-dialog',
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    content: {
      type: [Object, Function],
      required: true
    },
    contentProps: {
      type: Object,
      default: () => ({})
    },
    contentListeners: {
      type: Object,
      default: () => ({})
    }
  },
  render(h) {
    return h('el-dialog', {
      props: {
        visible: this.visible
      },
      attrs: this.$attrs,
      on: {
        ...this.$listeners,
        'update:visible': (val) => this.$emit('update:visible', val)
      }
    }, [
      // 手动创建传入组件的VNode
      h(this.content, {
        props: this.contentProps,
        on: this.contentListeners
      })
    ])
  }
};
</script>

两种方案都可以实现你的需求,优先推荐方案1,写法更简洁易维护。

内容的提问来源于stack exchange,提问作者CQ P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:15:04