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

VueJS组件动态创建展示复杂嵌套JSON对象的实现问题求助

核心问题分析

现有代码缺少父子层级绑定逻辑,无法区分新增的扩展是根节点还是某个complex类型节点的子节点,同时递归组件的props传参存在类型错误,导致无法嵌套展示。以下是完整修改方案:

1. 修改Vuex Store 逻辑

新增currentParentId字段记录当前新增节点的父ID,调整新增逻辑自动绑定父子关系,complex类型节点默认初始化children数组:

export const state = () => ({
  extensionID: 0,
  extensionList: [],
  showModal: false,
  // 新增:当前要添加的子节点所属父节点ID,根节点为null
  currentParentId: null
})

export const mutations = {
  toggleExtensionModal (state, parentId = null) {
    state.showModal = !state.showModal
    // 打开弹窗时记录父ID,关闭时重置
    if (state.showModal) {
      state.currentParentId = parentId
    } else {
      state.currentParentId = null
    }
  },
  addExtension (state, extension) {
    extension.ID = state.extensionID
    // complex类型默认添加children数组用于存子节点
    if (extension.dataType === 'complex') {
      extension.children = []
    }
    // 判断是根节点还是子节点
    if (state.currentParentId === null) {
      state.extensionList.push(extension)
    } else {
      // 递归查找父节点
      const findParent = (list) => {
        for (let item of list) {
          if (item.ID === state.currentParentId) return item
          if (item.children) {
            const res = findParent(item.children)
            if (res) return res
          }
        }
        return null
      }
      const parent = findParent(state.extensionList)
      if (parent) parent.children.push(extension)
    }
    state.extensionID++
  }
}

2. 修正ExtensionComponent递归组件

修复props传参错误,调整新增子节点的触发逻辑:

<template>
  <div style="margin-left: 20px;">
    <div
      v-for="extension in extensionList"
      :key="extension.ID"
      class="form-inline"
    >
      <span>{{ extension.namespace + ":" + extension.localName }}</span>
      <input
        v-if="extension.dataType == 'string'"
        type="text"
        v-model="extension.value"
      >
      <!-- 修正:传children数组给递归组件 -->
      <ExtensionComponent 
        v-if="extension.dataType == 'complex'" 
        :extension-list="extension.children" 
      />
      <button
        v-if="extension.dataType == 'complex'"
        @click="AddComplexExtension(extension.ID)"
        style="margin-left: 10px;"
      >
        Add another
      </button>
    </div>
  </div>
</template>

<script>
import ExtensionComponent from '@/components/ExtensionComponent.vue'

export default {
  name: 'ExtensionComponent',
  components: {
    ExtensionComponent
  },
  props: {
    extensionList: {
      type: Array,
      default: () => []
    }
  },
  methods: {
    AddComplexExtension (parentId) {
      // 打开弹窗时传入当前父节点ID
      this.$store.commit('toggleExtensionModal', parentId)
    }
  }
}
</script>

3. 调整Test.vue根页面逻辑

修正组件导入位置:

<template>
  <div>
    <span>Extensions</span>
    <button class="btn btn-primary" @click="createExtensions" style="margin-left: 10px;">
      Add Extension
    </button>
    <ExtensionComponent :extension-list="$store.state.extensionList" />
    <TestModal v-if="$store.state.showModal" />
  </div>
</template>

<script>
import TestModal from '@/components/TestModal.vue'
import ExtensionComponent from '@/components/ExtensionComponent.vue'

export default {
  components: {
    TestModal,
    ExtensionComponent
  },
  methods: {
    createExtensions () {
      // 根节点不传父ID
      this.$store.commit('toggleExtensionModal')
    }
  }
}
</script>

4. TestModal.vue无需大改,仅需重置表单数据

<script>
export default {
  data () {
    return {
      extension: {
        namespace: '',
        localName: '',
        dataType: 'string'
      }
    }
  },
  methods: {
    submitExtension () {
      // 深拷贝避免引用问题
      this.$store.commit('addExtension', JSON.parse(JSON.stringify(this.extension)))
      this.$store.commit('toggleExtensionModal')
      // 重置表单
      this.extension = { namespace: '', localName: '', dataType: 'string' }
    }
  }
}
</script>

最终效果

生成的JSON结构符合纵横双向扩展要求,示例如下:

[
  {
    "ID": 0,
    "namespace": "ns1",
    "localName": "ext1",
    "dataType": "string",
    "value": "测试文本"
  },
  {
    "ID": 1,
    "namespace": "ns2",
    "localName": "ext2",
    "dataType": "complex",
    "children": [
      {
        "ID": 2,
        "namespace": "ns3",
        "localName": "ext3",
        "dataType": "complex",
        "children": [
          {
            "ID": 3,
            "namespace": "ns4",
            "localName": "ext4",
            "dataType": "string",
            "value": "嵌套文本"
          }
        ]
      }
    ]
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:09:03