以姓名案例为版本,使用 watch 实现
<div id="root">
<div>姓:<input type="text" v-model='firstName'></div>
<div>名:<input type="text" v-model='lastName'></div>
<div>全名:{{fullName}}</div>
</div>
<script>
const vm = new Vue({
el: '#root',
data() {
return {
firstName: '张',
lastName: '三',
fullName: '张-三'
}
},
watch: {
firstName(newValue, oldValue) {
this.fullName = newValue + '-' + this.lastName
},
lastName(newValue, oldValue) {
this.fullName = this.firstName + '-' + newValue
}
}
})
</script>
1、页面展示的 fullName 需要在 data 内部自定义,否则页面报错(不同于计算属性)
2、因为 firstName 和 lastName 都是一般类型数据,不需要开启深度监听,所以简写成函数模式
3、在watch 内部监听 firstName 和 lastName 时,接收两个参数,但是我们只需要使用newValue
4、在监听函数内部,对 fullName 进行处理,使其在页面上展现出改变后的值
对比一下之前的计算属性版本可以发现 ,使用 watch 监听之后,区别在于:
1、watch 监听需要在 data 内部定义 fullName 属性,而计算属性则是写在 computed 内部的属性
2、watch 中需要监听每个属性的改变,然后改变 fullName 的值,造成了代码重复,且是命令式的
3、
这么看起来,是不是 computed 要方便很多了?代码量少,且逻辑简单,data内还不用自定义属性,但是,计算属性内不能开启异步任务 就是计算属性最大的局限性
开启异步任务
还是上面的例子,但是添加了一个需求,在我改变姓或名之后,延迟1s之后,在进行改变,然后通过两种方式分别进行
watch:在延迟一秒之后,仍然可以输出正确的 fullName
watch: {
firstName(newValue, oldValue) {
setTimeout(() => {
this.fullName = newValue + '-' + this.lastName
}, 1000)
},
lastName(newValue, oldValue) {
this.fullName = this.firstName + '-' + newValue
}
}
计算属性:setTimeout 的返回值 只有一个定时器 id,且一般只是用来清除定时器,所以 fullName 函数,是没有显式的返回值的,默认的返回值 就是 undefined,那么即使改变了姓或名,但是 fullName 在初始化 和 后续改变之后,也是无法获得返回值的。
computed: {
fullName: function () {
setTimeout(() => {
console.log('计算属性被调用了')
return this.firstName + this.lastName
}, 1000)
}
},
本章小结
computed 和 watch 之间的区别:
1、computed 能实现的,watch 都能实现
2、watch能完成的,computed 不一定能实现。例如:开启异步任务
ps:
1、被 Vue 管理的函数,尽量写成普通函数,使得 函数内部 this 指向 vm 或 组件实例对象
2、所有不被 Vue 管理的函数(定时器回调,ajax回调,Promise回调),最好也写成箭头函数,由此来继承外部this,使得 函数内部 this 指向 vm 或 组件实例对象