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

Vue3子组件访问$slot数据触发循环结构转JSON错误

Vue3模板打印插槽对象触发循环引用错误的解决办法

问题根源

在模板里写<pre>{{ $slots.title() }}</pre>时,Vue会尝试把插槽返回的VNode对象转成JSON字符串展示,但VNode内部包含父节点、上下文这类循环引用的属性,直接序列化就会触发TypeError: Converting circular structure to JSON。而在<script>里用console.log能正常输出,是因为浏览器控制台会自动处理循环引用的展示。

可行解决方案

1. 直接取插槽文本内容(纯文本插槽适用)

如果你的title插槽只传了纯文本,直接访问VNode的children就能拿到内容:

<pre>{{ $slots.title()[0].children }}</pre>

2. 在脚本里处理插槽结构,提取有用信息

要是想查看完整的插槽结构,先在<script setup>里用useSlots获取插槽,然后提取非循环引用的属性,再放到模板里展示:

<script setup>
import { defineProps, defineEmits, useSlots } from 'vue'

const props = defineProps({
  btnStyle: String,
})
const emit = defineEmits(['close'])
const slots = useSlots()

// 过滤掉会导致循环引用的属性
const formatSlotInfo = () => {
  const titleSlot = slots.title?.() || []
  return titleSlot.map(vnode => ({
    类型: vnode.type,
    内容: vnode.children,
    属性: vnode.props
  }))
}
const slotInfo = formatSlotInfo()
</script>

<template>
  <teleport to="#modals-container">
    <div class="modal z-10 absolute top-0 left-0 w-full h-full p-10 bg-yellow-50">
      <h1><slot name="title" /></h1>
      <slot />
      <pre>{{ slotInfo }}</pre>
      <button :class="btnStyle" @click="$emit('close')">Hide modal</button>
    </div>
  </teleport>
</template>

3. 用JSON.stringify的replacer跳过循环引用属性

直接在模板里用JSON.stringify配合替换函数,跳过那些会引发循环引用的属性:

<pre>{{ JSON.stringify($slots.title(), (key, value) => {
  // 忽略parent、ctx这类循环引用属性
  if (key === 'parent' || key === 'ctx') return undefined
  return value
}, 2) }}</pre>

关于移除()后输出无意义的说明

去掉()后,$slots.title是一个函数引用,模板里直接展示的是函数的字符串形式(比如function() { [native code] }),自然没意义。课程视频里的输出应该是在脚本中打印,或者做了专门的处理,和模板直接展示的逻辑不一样。

内容的提问来源于stack exchange,提问作者Leon Gaban

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:15:23