我正在向Vue.js(2.5.16 版)介绍自己,但在理解Reactivity的问题时遇到了问题:
我有两个组件列表,其中v-for
大部分时间都正确呈现循环 - 我可以与组件交互并添加新组件。这些组件与表示“区域”的 REST API 交互,我希望其功能相当明显 - 它主要返回单个或所有“区域”的 JSON 表示,例如:
{
"state": "off",
"pin": 24,
"uri": "/zones/6",
"name": "extra"
}
每当添加或删除区域时,应用程序都会重新加载整个区域列表。但是,由于某种原因,当我删除一个区域并触发重新加载区域时,列表会使用错误的数据呈现!无论我删除哪个区域,列表的最后一项似乎都“弹出”了,而不是预期的区域没有出现在新列表中!当我检查 app.zones 数据时,Javascript 数据中的所有内容都显示正确,但它只是没有显示在浏览器中。
以下是相关代码:
...
<div class="tab-content">
<div id="control" class="tab-pane fade in active">
<ul>
<zone-control
v-for="zone in zones"
v-bind:init-zone="zone"
v-bind:key="zone.id">
</zone-control>
</ul>
</div>
<div id="setup" class="tab-pane fade">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Pin</th>
<th></th>
</tr>
</thead>
<tbody>
<tr is="zone-setup"
v-for="zone in zones"
v-bind:init-zone="zone"
v-bind:key="zone.id">
</tr>
<tr is="zone-add"></tr>
</tbody>
</table>
</div>
</div>
...
<script>
Vue.component('zone-control', {
props: ['initZone'],
template:
`<li>
<div class="btn btn-default" v-on:click="toggleState">
<span v-if="zone.state == 'on'" class="glyphicon glyphicon-ok-circle text-success"></span>
<span v-else class="glyphicon glyphicon-remove-sign text-danger"></span>
Zone: {{ zone.name }}
</div>
</li>`,
data: function() {
return {
zone: this.initZone
};
},
methods: {
toggleState: function() {
var state = (this.zone.state == 'on' ? 'off' : 'on');
console.log('Turning zone ' + this.zone.name + ' ' + state);
var comp = this
fetch(
this.zone.uri,
{method: 'PUT',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: JSON.stringify({state: state})
}).then( function(result) {
return result.json()
}).then( function(data) {
comp.zone = data;
});
}
}
})
Vue.component('zone-setup', {
props: ['initZone'],
template:
`<tr>
<td>{{ zone.name }}</td>
<td>{{ zone.pin }}</td>
<td><div v-on:click="deleteZone" class="btn btn-danger btn-small"></div></td>
</tr>`,
data: function() {
return {
zone: this.initZone
};
},
methods: {
deleteZone: function() {
fetch(
this.zone.uri,
{method: 'DELETE'}
).then( function(result) {
app.load_zones();
});
}
}
})
Vue.component('zone-add', {
template:
`<tr>
<td><input v-model="zone.name" type="text" class="form-control"></input></td>
<td><input v-model="zone.pin" type="text" class="form-control"></input></td>
<td><div v-on:click="addZone" class="btn btn-success btn-small"></div></td>
</tr>`,
data: function() {
return {
zone: {
name: '',
pin: ''
}
};
},
methods: {
addZone: function() {
console.log('Adding zone ' + this.zone.name);
var comp = this
fetch(
"/zones",
{
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: JSON.stringify({
name: comp.zone.name,
pin: comp.zone.pin})
}
).then( function(result) {
app.load_zones()
comp.zone = {}
});
}
}
})
var app = new Vue({
el: '#app',
data: {
zones: []
},
methods: {
load_zones: function() {
fetch("zones")
.then(function(result){
return result.json()
}).then(function(data){
app.zones = data;
});
}
},
created: function() {
this.load_zones();
}
})
</script>
我已经阅读了几篇参考资料,似乎有一些边缘案例或其他“问题”,但这似乎不属于其中任何一个。例如,另一个问题似乎同意替换整个数组是在 Vue.js 反应性系统的约束内更改数组的一种非常简单的方法。
我检查过的其他一些指向Vue.js 文档的链接是相关的,但似乎并不指向我的问题:
有关上下文中的完整代码,请参阅此处的 github 存储库。
更新
根据评论,我在简化的JSBin中重现了这些症状。单击任何按钮可以看到,当第二个元素应该被删除时,最后一个元素会被删除!