vue.js 渲染深度未知的嵌套数组对象

vhipe2zx  于 7个月前  发布在  Vue.js
关注(0)|答案(1)|浏览(66)

如何在UI上呈现和显示嵌套元素(来自对象的嵌套值[]字段),这些值在选择选项时动态生成例如,我得到了下面的代码。当你创建字段并选择列表选项时,你应该看到一个嵌套的等等,深度是未知的。我如何呈现这一点以显示给用户?在v-for里面的v-for似乎不起作用。也许我需要递归,但我不知道如何释放它。
我感谢任何帮助!

var app = new Vue({
    el: '.container',
    data: {
        modelname: '',
                fields: []
    },
    methods: {

        addNewField() {
            this.fields.push({
            left: 0,
            type:'',
            method:'',
            size:'',
            value:''}
            )
        },
        createChildElement(field) {
        if (field.type == "List") {
        Vue.set(field, "value", []);
        field.value.push({
                   type:'',
                   left: field.left+20,
                   method:'',
                   size:'',
                   value:''}
                   );
 }
        
        },
        showJson() {
        const data = this.fields
    alert(JSON.stringify(data, null, 2));
        }
    }
})

个字符

**UPD.**基于答案,我试图为我的任务制定一个解决方案,但我仍然有一些问题。我将大部分代码移动到组件,但我收到了很多我无法解决的错误。例如:

Invalid prop: type check failed for prop "item". Expected Object, got Array.

Property or method "fields" is not defined on the instance but referenced during render.


下面是我的代码:

Vue.component("el-inpt-group", {
        template: "#item-template",
        props: {
            item: Object,
          }
          });


var app = new Vue({
    el: '.container',
    data: {
        modelname: '',
        fields: [
        ]
    },
    methods: {

        addNewField() {
            this.fields.push({
            name: '',
            left: 0,
            type:'',
            method:'',
            size:'',
            value:''}
            )
        },
        createChildElement(field) {
        if (field.type == "List") {
        Vue.set(field, "value", []);
        field.value.push({
        name: '',
                   type:'',
                   left: field.left+20,
                   method:'',
                   size:'',
                   value:''}
                   )
        }
        },
        showJson() {
        const data = this.fields
    alert(JSON.stringify(data, null, 2));
        }
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

    <script type="text/x-template" id="item-template">
            <ul>
                <li v-for="field in fields">
                    <input type="text"  v-model="field.name" placeholder="Name">
                    <select  v-model="field.type" v-on:change="createChildElement(field)"  aria-label="Выбрать тип поля">
                        <option selected>Тип поля</option>
                        <option value="List">List</option>
                        <option value="Map">Map</option>
                        <option value="Integer">Integer</option>
                    </select>
                    <select  v-model="field.method" v-if="field.type === 'Map' || field.type === 'List'"  aria-label="Метод генерации">
                        <option selected>Тип значения</option>
                        <option value="Static">Static</option>
                        <option value="Random">Random</option>
                        <option value="Range">Range</option>
                    </select>
                    <input type="text" v-if="field.type === 'Map' || field.type === 'List'"  v-model="field.size" placeholder="Размерность">
                    <input type="text" v-if="field.type === 'Integer'"  v-model="field.value" placeholder="Значение">
                </li>
                <ul><el-inpt-group v-for="child in fields.value" :style="{marginLeft: field.left+'px'}" :key="child.name" :item="child"></el-inpt-group></ul>
            </ul>
    </script>
</head>
<body>
<div class="container">
            <h1 class="font-italic text-warning">TDGT Web Client</h1>
           
                <button id="add-field" class="btn btn-sm btn-warning" @click="addNewField">Create field</button>
                <button id="show-json" class="btn btn-sm btn-warning" @click="showJson">Show JSON</button>
                <el-inpt-group :item="fields"></el-inpt-group>

            </div>
    </div>

的字符串

6yoyoihd

6yoyoihd1#

事实上,递归是这里的解决方案。
当你不知道如何正确组织代码时,这通常意味着你没有将代码划分为足够的组件。
举一个简单的例子,只需创建一个以一个项为属性的组件,然后在该项具有子项时调用它自己。
给定此示例结构:

[
  {
     name: 'Todo 1'
  },
  {
     name: 'Todo 2',
     items: [
       {
          name: 'Todo 2.1'
       },
       {
          name: 'Todo 2.2'
       }  
     ],
  },
  {
     name: 'Todo 3',
     items: []

  },
]
<template>
   <div>
      <article v-for="subTodos of todo.items" :key="subTodos.name"> 
          <h1>{{ subTodos.name }}</h1>
          <Todo :todo="subTodos" />
      </article>
   </div>
</template>

<script>
export default {
  name: 'Todo',
  props: {
    todo: { type: Object, required: true }
  }
}
</script>
<template>
   <Todo :todo="firstItem" />
</template>

<script>
export default {
   data () {
     return {
       firstItem: { name: 'First todo', items: nestedTodos }
     }
   }
}
</script>

在这里,只要todo.items不是空数组,它就会创建一个<Todo>组件,这个组件会创建更多的<Todo>元素,只要这些元素本身有元素。

相关问题