watch与computed作为Vue中两个处理响应式数据的选项,都用来监听数据变化并执行相应的逻辑,在具体使用时会存在区别:
watch用于监听指定的数据变化并执行相应的回调函数,它有两种写法:
watch: {
shops: {
handler(oldValue, newValue) {
// 写一些逻辑,当shops参数发生变化时就会执行
}
},
visible: {
handler(oldValue, newValue) {
// 写一些逻辑,当visible参数发生变化时就会执行
}
}
},
当需要设置深层监视时(如要监视一个对象时),则需要开启deep属性:
watch: {
shops: {
handler(oldValue, newValue) {
// 写一些逻辑,当shops参数发生变化时就会执行
},
deep: true
}
}
当需要在初始时立即执行监听回调函数时,需要设置immediate属性:
watch: {
shops: {
handler(oldValue, newValue) {
// 写一些逻辑,当shops参数发生变化时就会执行
},
immediate: true
}
}
当不需要深层监视或立即监听时,就可以通过如下简单方式:
watch: {
shops(oldValue, newValue) {
// 写一些逻辑,当shops参数发生变化时就会执行
},
visible(oldValue, newValue) {
// 写一些逻辑,当visible参数发生变化时就会执行
}
},
该种方式适合对Vue实例进行监听,语法如下:
vm.$watch(
expression, // 被观察的表达式,可以是一个函数或者一个字符串
callback, // 数据变化时的回调函数
options // 选项,可选
);
const vm = new Vue({
// vm 即为创建的vue实例
data() {
return {
message: 'Hello, Vue!'
};
},
created() {
// 使用 $watch 监视 message 的变化
vm.$watch(
'message',
(newVal, oldVal) => {
console.log(`message 发生变化:${oldVal} -> ${newVal}`);
},
{
deep: true,
immediate: true
}
);
// 修改 message,触发回调函数
this.message = 'Updated Message';
// 控制台输出:message 发生变化:Hello, Vue! -> Updated Message
}
});
computed用于创建基于响应式数据计算而来的属性,该属性可以在模板中直接使用,只有当相关响应式数据发生变化时才会重新计算,computed选项相当于对数据的一种加工
computed: {
// 基于data中的属性计算得到
fullName() {
// 在firstName或lastName发生变化时会自动计算
return this.firstName + ' ' + this.lastName;
},
// 基于其他computed属性计算得到
// 在fullName发生变化时会自动计算
reversedFullName() {
return this.fullName.split('').reverse().join('');
}
}
① 二者都是基于Vue的依赖收集机制
② 都是由被依赖的变化触发,从而进行处理计算
① 时机上,computed从首次被赋值时就被计算,而watch不会,需要设置immediate: true才能立即监听
② 性能上,computed会自动进行diff计算,若所依赖项未发生变化,则会从缓存中取值;而watch在每次监听的值发生变化的时候都会执行回调。computed的性能会高
从源码看计算属性:
????computed会创建一个计算属性watcher,这个watcher(lazy:true)不会立即执行;通过Object.defineProperty将计算属性定义到实例上;当用户取值时会触发getter,拿到计算属性对应的watcher,看dirty是否为true,如果为true则求值;并且让计算属性watcher中依赖的属性收集最外层的渲染watcher,可以做到依赖的属性变化了,触发计算属性更新dirty并且触发页面更新;如果依赖的值没有发生变化,则采用缓存。
③ 写法上,computed必须要有返回值,而watch不用;
④ 异步上,computed不支持异步,watch支持异步,支持在回调函数上引入异步方法
⑤ 是否能与data中的属性命名重复, watch必须要监视在data中定义过的属性,computed则不能与data中的属性命名重复
????在具体的应用场景下,一般而言,当一个属性受多个属性影响的时候,使用computed,当需要监测一个属性的变化对其它属性的影响时,使用watch