我正在尝试学习Vuejs,并且遇到了一个非常基本的问题。我有很多击倒和胡子的经验,我认为这可能是导致我问题的原因。
我正试图构建一个简单的复选框列表,以处理绑定,但我的模型没有更新,我在控制台中收到以下警告:
避免直接改变属性,因为值将被覆盖
每当父组件重新呈现时。而是使用数据或
基于属性值的计算属性。正在变异的道具:
“核对”
这就是我想要做的;
表示待办事项的简单视图模型:
function vmToDoItem(id, title){
this.id = id;
this.title = title;
this.complete = false;
}
表示所有待办事项的简单视图模型:
function vmToDo(items){
var self = this;
self.currentFilter = 'all';
self.items = items || [];
self.filters = {
all: function(){
return self.items;
},
active: function(){
return self.items.filter((item) => !item.complete);
},
complete: function(){
return self.items.filter((item) => item.complete);
}
}
}
表示待办事项的组件:
Vue.component('checkbox-item',
{
props: ['text', 'checked'],
template: '#checkbox-item-template',
computed: {
prefix: function(){
return !this.checked ? 'fa-circle' : 'fa-check-circle';
}
},
methods: {
clicked: function(){
this.checked = !this.checked;
}
}
})
对应模板:
<script type="text/x-template" id="checkbox-item-template">
<span @click="clicked">
<span :class="'far ' + prefix"></span>
{{ text }}
</span>
</script>
“app”的标记:
<div id="app">
<checkbox-item
v-for="item in items"
class="todoItem"
:key="item.id"
v-bind:text="item.title"
v-bind:checked="item.complete">
</checkbox-item>
<br />
<span>Items unchecked: {{ remaining }}</span>
</div>
初始化代码:
var mdl = new vmToDo();
mdl.items.push(new vmToDoItem(1, 'test 1'));
mdl.items.push(new vmToDoItem(2, 'test 2'));
var vm = new Vue({
el: '#app',
data: mdl,
computed: {
remaining: function(){
let currentFilter = this.$data.filters[this.$data.currentFilter];
return currentFilter().length;
}
}
});
所有东西都呈现得很好,单击其中一个项可以正确地切换复选框,但是mdl.items中的基础项没有更新,我在控制台中收到上述警告。
我怀疑双向绑定的工作方式与我预期的不同,我预期它的工作方式会像淘汰一样,我对如何使这个函数像我预期的那样工作感到困惑。
为了简洁起见,以下是我的问题的完整片段:
function vmToDoItem(id, title){
this.id = id;
this.title = title;
this.complete = false;
}
function vmToDo(items){
var self = this;
self.currentFilter = 'all';
self.items = items || [];
self.filters = {
all: function(){
return self.items;
},
active: function(){
return self.items.filter((item) => !item.complete);
},
complete: function(){
return self.items.filter((item) => item.complete);
}
}
}
Vue.component('checkbox-item',
{
props: ['text', 'checked'],
template: '#checkbox-item-template',
computed: {
prefix: function(){
return !this.checked ? 'fa-circle' : 'fa-check-circle';
}
},
methods: {
clicked: function(){
this.checked = !this.checked;
}
}
})
var mdl = new vmToDo();
mdl.items.push(new vmToDoItem(1, 'test 1'));
mdl.items.push(new vmToDoItem(2, 'test 2'));
var vm = new Vue({
el: '#app',
data: mdl,
computed: {
remaining: function(){
let currentFilter = this.$data.filters[this.$data.currentFilter];
return currentFilter().length;
}
}
});
#app span.todoItem{
display: inline-block;
cursor: pointer;
padding-right: 1em;
}
#app span.todoItem span.far {
vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="//use.fontawesome.com/releases/v5.6.3/css/regular.css" />
<link rel="stylesheet" href="//use.fontawesome.com/releases/v5.6.3/css/fontawesome.css" />
<div id="app">
<checkbox-item
v-for="item in items"
class="todoItem"
:key="item.id"
v-bind:text="item.title"
v-bind:checked="item.complete">
</checkbox-item>
<br />
<span>Items unchecked: {{ remaining }}</span>
</div>
<script type="text/x-template" id="checkbox-item-template">
<span @click="clicked">
<span :class="'far ' + prefix"></span>
{{ text }}
</span>
</script>