Vue.js 在Vue中观察计算属性的反应性触发器
通常,在使用Vue时,我希望仅当监视的属性的值更改时才会触发该属性的回调。但是,一位同事注意到,在查看计算属性时,这似乎不成立,如下例所示:Vue.js 在Vue中观察计算属性的反应性触发器,vue.js,Vue.js,通常,在使用Vue时,我希望仅当监视的属性的值更改时才会触发该属性的回调。但是,一位同事注意到,在查看计算属性时,这似乎不成立,如下例所示: <div id = "demo"> {{ numbers }} </br> {{ evenNumbers }} </div> <script src="./vue.js"></script> <script> var demo = new Vue({
<div id = "demo">
{{ numbers }} </br>
{{ evenNumbers }}
</div>
<script src="./vue.js"></script>
<script>
var demo = new Vue({
el: '#demo',
data: function(){
return {
numbers: [1,2,3,4,5,6]
};
},
computed: {
evenNumbers: function () {
return this.numbers.filter(x => (x % 2 == 0))
}
},
watch: {
evenNumbers: function (val) {
alert("yes, computed property changed")
}
}
})
setTimeout(() => { demo.numbers.push(7) }, 5000)
</script>
{{numbers}}
{{evenNumbers}}
var demo=新的Vue({
el:'演示',
数据:函数(){
返回{
编号:[1,2,3,4,5,6]
};
},
计算:{
偶数:函数(){
返回此.numbers.filter(x=>(x%2==0))
}
},
观察:{
偶数:函数(val){
警报(“是,计算属性已更改”)
}
}
})
setTimeout(()=>{demo.numbers.push(7)},5000)
5s后,将显示警报,但计算数字数组的值不会更改。如果计算属性的依赖项更新,即使计算属性本身没有更新,也很容易推断会触发监视程序
事实证明,对于我们正在开发的应用程序来说,这很适合我们,但我不理解它的行为,我不知道我们是否可以依赖它,或者在什么条件下它可以保持。(例如,我这里有两个数组,但如果我使用原语,它还能工作吗?我不知道,如果我有时间,我可能会进行实验,但当我键入此内容时,我首先想到的是比较对象相等性的问题,其次是Vue的反应性和复合对象的缺陷。)我还可以想象,如果回调给你的观察者是一项昂贵的操作,那可能会是一个令人不快的惊喜
如果有人能解释这是如何工作的,如果我们能依靠这种行为,我将不胜感激。监视程序被触发,因为它无法知道
数据.数字的更改是否会影响计算的.evenNumbers
的结果
但是,在重新计算时,它发现7不是偶数,因此数组仍然是[2,4,6]
如果要确保回调仅在值实际更改时运行,可以将其指定为
watch: {
evenNumbers(newValue, oldValue){
if(newValue !== oldValue) {
alert('callback')
}
}
}
每次执行evenNumbers()
时,它都会生成一个全新的数组。因为数组是通过引用相等来比较的,所以它们永远不可能相等。正确检测此更改的唯一方法是手动比较以前计算的数组和新计算的数组的内容
例如,使用lodash:
import { isEqual } from 'lodash';
...
watch: {
evenNumbers(newValue, oldValue) {
if(!isEqual(newValue, oldValue) {
alert('callback')
}
}
}
你可能会觉得很有帮助。我希望它能像对待其他数据一样对待计算结果——毕竟,它必须这样做才能让这个建议起作用。但是这个建议很有帮助,所以每次执行evenNumbers()时,它都会生成一个全新的数组。因为数组是通过引用相等来比较的,所以它们永远不可能相等。正确检测此更改的唯一方法是手动比较以前计算的数组和新计算的数组的内容。你说得对,Mattias。下划线或lodash中有一些方法可以为您进行适当的平等性检查。@MattiasMartens刚刚再次查看了这一点-如果您想感谢@rwold,很高兴将您的观察结果作为一个可接受的答案-我已将我的评论作为一个答案发布。