我将自己介绍给 Vue.js(版本2.5.16),但遇到了解决反应性的问题的问题:< / p>
我有两个组件列表,其中v-for
循环可以在大多数情况下正确呈现 - 我可以与组件交互并添加新组件。这些组件与代表区域的REST API交互,并且我希望它的功能相当明显 - 它主要返回单个或所有区域的JSON表示&#39;例如:
{
"state": "off",
"pin": 24,
"uri": "/zones/6",
"name": "extra"
}
每当添加或删除区域时,应用都会重新加载整个区域列表。但是,出于某种原因,当我删除区域并触发重新加载区域时,列表会使用错误的数据进行渲染!无论我删除哪个区域,列表的最后一项似乎都会弹出&#39;而不是新列表中未显示的预期区域!当我检查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>
我已经阅读了几篇参考文献,似乎有一些边缘案例或其他“gatchas”#39;但这似乎不属于任何一个。例如,this other question似乎同意在Vue.js反应系统的约束下更换整个数组是一种非常简单的改变数组的方法。
我已经检查过的 Vue.js文档的其他一些链接,但这些链接似乎与我的问题无关:
有关上下文中的完整代码,请参阅github repo here。
根据评论,我用简化的JSBin复制了这些症状。单击任何按钮以查看,当应删除第二个元素时,最后一个元素将被删除!
答案 0 :(得分:0)
好的,我弄清楚了:它是v-bind:key
的全部内容。我意识到我已经绑定了一个属性,该属性不是由我提供数据的API提供的。引用每个组件的(真实的)唯一属性,问题就消失了。
我注意到List Rendering Documentation提及了
在2.2.0+中,当对组件使用v-for时,现在需要一个键。
有趣的是,我上面链接的JSBin
显着使用 Vue.js版本2.0.3 ,但问题仍然存在,并通过正确使用key
属性来解决在v-for
循环中。
如果有其他人想看到这一点,请查看问题中关联的JSBin
,并在v-bind:key="zone.id"
元素中添加<tr>
。之后问题就解决了。