如何在 UI 上呈现和显示嵌套元素(来自对象的嵌套 value[] 字段),这些元素是在父元素中选择选项(例如列表)时动态生成的? 例如,我在下面得到了这个代码。当您创建字段并选择 List 选项时,您应该会看到一个嵌套等,深度未知。我怎样才能呈现这个以显示给用户? 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));
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
<h1 class="font-italic text-warning">TDGT Web Client</h1>
<!--<button id="add-model" class="btn btn-warning" @click="addNewModel">Создать модель</button>-->
<div>
<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>
<div v-for="(field, index) in fields" :style="{marginLeft: field.left+'px'}" :key="index">
<ul>
<li>
<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></ul>
</ul>
</div>
</div>
</div>
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>
答案 0 :(得分:0)
确实递归是您的解决方案。
当您看不到如何正确组织代码时,通常意味着您没有将代码划分为足够多的组件。
举个简单的例子,只需要创建一个组件,将一个item作为属性,然后当这个item作为子item时调用自己。
鉴于此示例结构:
[
{
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>
元素...< /p>