之前在介绍过vue computed原理分析:vue computed原理分析,今天来看一个我遇到的关于computed比较奇怪的问题:
需求比较简单,一个页面上有一个勾选框,还有一个数组(列表,可以通过按钮添加),需要数组中有内容并且是选中状态提交按钮才会点亮。代码如下:
至少添加一个项目且勾选才能提交
添加项目
- {{item}}
是否勾选
const app = new Vue({
el: '#app',
data: {
check: false, //是否选中
list: [],
value: '',
},
computed: {
canSubmit: function() {
console.log('触发执行canSubmit');
return this.list.length && this.check;
}
},
mounted: function() {
},
methods: {
addItem: function() { //增加项目
if(this.value) {
this.list.push(this.value);
this.value = '';
}
}
}
})
其中按钮点亮用的是一个computed:canSubmit,根据list和check判断:return this.list.length && this.check;
因为computed中同时关联了check和list,那么按理说check或list发生变化的时候,canSubmit应该变化的,但是看上图可以发现,当list为空的时候(未添加),触发check的时候,canSubmit并无任何变化!!
虽然这个小细节并不影响整体的功能,但是我们仔细思考一下,为什么当list为空的时候,改变check无法改变canSubmit呢?
问题分析
这个其实和computed的实现原理有关,不太熟悉的朋友,可以点进文章开头的链接去看看原理。computed之所有可以关联多个变量,是因为执行computed方法的时候,内部调用了data上的对象,(list,check),执行了getter,才会让Dep和Watcher关联上。
我们的方法是return this.list.length && this.check;第一个条件为false,那么第二个条件自然也就不执行了,因此check和canSubmit之间没有关联关系。只有list和canSubmit的关联关系。所以当list没有数据的时候,修改check并不会改变canSubmit。
但是当list有数据的时候,canSubmit会执行,此时的this.list.length得到的true,会执行到this.check,因此此时check又和canSubmit恢复了绑定关系。
问题规避
通过上面的分析可以得到,如果变量直接和&&,||之类一起执行的时候,可能导致不执行,因此我们要确保变量都执行了getter:
computed: {
canSubmit: function() {
let len=this.list.length,
_check=this.check;
return len && _check;
}
},
改成上面那样,无论list有没有数据,都可以取保执行了this.check,那么check就和canSubmit就可以保持关联了。