我刚刚开始使用Vue.js,但是我遇到了Vue.js反应性数据源的一些问题。
以下代码应能够添加和删除在父元素中包含文本字段和文本区域的行。
ElementsView.vue
<template>
<div>
<label></label>
<br>
<small class='text-muted'></small>
<br>
<div class='marks_content'>
<div class='row' v-for="(item, index) in marks" v-bind:key="index">
<div class='col-md-12 mark_header_container'>
<div class="numerator-element">
<span class="numerator-content">{{ index + 1 }}</span>
</div>
<div class="remove-button" v-on:click="removeMark(index)">
</div>
</div>
<div class='col-md-6'>
<TextField :element-id='"term_textfield" + index' :message="item.term" type='text' placeholder="Kenmerk / element / fase"></TextField>
</div>
<div class='col-md-6'>
<TextField :element-id='"desc_textfield" + index ' :optional="true" :message="item.description" type='text' placeholder="Beschrijving (optioneel)" multiline="true"></TextField>
</div>
</div>
</div>
<div class='row'>
<div class='col-md-6'>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="order_check">
<label class="form-check-label" for="order_check">Volgorde van belang (bij fases)</label>
</div>
</div>
<div class='col-md-6 right_column'>
<a href="#" v-on:click="addMark">Nieuwe rij toevoegen</a>
</div>
</div>
</div>
</template>
<script>
import TextField from './TextField.vue'
export default {
props: ['elements'],
name: 'ElementsView',
components: {
TextField
},
data() {
return {
marks: [{}]
}
},
mounted() {
if (this.elements) {
if (this.elements.length > 0) {
this.marks = this.elements;
}
}
},
methods: {
addMark: function (e) {
this.marks.push({ 'term': '', 'description': ''}); //I thought the issue might be related to having undefined values, so I changed it to empty strings
},
removeMark: function(index) {
//this.marks = [{ 'term': 'term1', 'description': 'desc1'}, { 'term': 'term12', 'description': 'desc13'}]
this.marks.splice(index, 1);
}
}
}
</script>
TextField.vue
<template>
<div class="form-group">
<label v-if="title" :for="elementId">{{title}}</label>
<textarea v-if="multiline" v-bind:class="{ optional: optional }" rows="1" :type="type" class="form-control" :id="elementId" :aria-describedby="elementId + '_help'" :placeholder="placeholder" v-model="messageValue"></textarea>
<Input :value="message" v-bind:class="{ optional: optional }" v-else rows="1" :type="type" class="form-control" :id="elementId" :aria-describedby="elementId + '_help'" :placeholder="placeholder"/>
<small v-if="help" :id="elementId + '_help'" class="form-text text-muted">{{help}}</small>
</div>
</template>
<script>
import autosize from 'autosize';
export default {
props: ['elementId', 'type', 'title', 'help', 'placeholder', 'multiline', 'message', 'optional'],
name: 'TextField',
data() {
return {
messageValue: this.message
}
},
mounted() {
var root = this.$el;
var textAreas = root.getElementsByTagName("TextArea");
if (textAreas.length > 0) {
var area = textAreas[0];
autosize(area);
}
}
}
</script>
我想在起点处有一个空行,在代码中用标记[[}]表示。每当用户想要添加新行时,都会向数组添加新的空json对象。这可以正常工作,但是删除对象会导致错误。
该数组由未绑定到行元素中任何输入的空对象组成,因此该数组由空JSON对象组成。因此,我希望接口重新呈现行元素的数量-删除元素后为1,并且不显示用户先前编写的任何文本。
情况并非如此,即使新对象为空,用户之前输入的输入仍然可见。对于addMark函数(这不是问题,但不是我所期望的)和removeMark函数(我看到随机行都消失了)都发生了这种情况。
最初,我认为有必要在更改列表之前更新列表所依赖的数据,因为这将迫使它与数组一起从数据对象中重绘。
为了测试这个假设,我尝试在removeMark函数中分配另一个数组(仅出于测试目的),然后看看会发生什么。当未修改输入时,这似乎可以部分起作用,但是当修改输入时,此新数组值将被覆盖。
有人可以指出我做错了什么吗?
答案 0 :(得分:1)
问题是这一行:
<div class='row' v-for="(item, index) in marks" v-bind:key="index">
您正在将数组的索引作为标识符绑定到呈现的条目。当删除另一个项目时,该项目的索引会更改,因此无法使用。这解释了看似随机的行为。实际上,重新渲染无法正常工作。
如果您有一个唯一标识符,则可以使用它。如果条目term
是唯一的:
<div class='row' v-for="(item, index) in marks" v-bind:key="item.term">
如果term
不是唯一的,则您可以自己创建一个id并将其用作键:
<div class='row' v-for="(item, index) in marks" v-bind:key="item.id">
对于唯一的,丢弃的id,当前时间戳是可行的。更改addMark以创建ID:
addMark: function (e) {
this.marks.push({ 'term': '', 'description': '', id: (new Date()).valueOf() });
}