watch 和 computed的区别是:
相同点:他们两者都是观察页面数据变化的。
不同点:computed
只有当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据。watch
每次都需要执行函数。watch
更适用于数据变化时的异步操作。
一、computed计算属性
computed
是计算属性,它会根据所依赖的数据动态显示新的计算结果, 该计算结果会被缓存起来。computed
的值在getter
执行后是会被缓存的。如果所依赖的数据发生改变时候, 就会重新调用getter
来计算最新的结果。
computed
的使用场景:适用于一些重复使用数据或复杂及费时的运算。我们可以把它放入computed
中进行计算, 然后会在computed
中缓存起来, 下次就可以直接获取了。
举个例子:
//html部分<div id="app"> <p>原来的数据: {{ msg }}</p> <p>反转后的数据为: {{ reversedMsg }}</p></div>
//js部分var vm = new Vue({ el: '#app', data: { msg: 'hello' }, computed: { reversedMsg() { return this.msg.split('').reverse().join('') } } });
以上代码中,使用computed
来进行计算属性值,vm.reversedMsg
的值依赖于 vm.msg
的值,当vm.msg
的值发生改变时, vm.reversedMsg
的值也会得到更新。
二、watch监听
watch
用来监听数据。它会对data
的数据监听回调, 当依赖的data
的数据变化时, 会执行回调。在回调中会传入newVal
和oldVal
两个参数。
Vue实列将会在实例化时调用$watch()
, 他会遍历watch
对象的每一个属性。
watch
的使用场景是:当在data
中的某个数据发生变化时, 我们需要做一些操作, 或者当需要在数据变化时执行异步或开销较大的操作时. 我们就可以使用watch
来进行监听。
举个例子:
<div id="app"> <p>空智个人信息情况: {{ basicMsg }}</p> <p>空智今年的年龄: <input type="text" v-model="age" /></p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { basicMsg: '', age: 31, single: '单身' }, watch: { age(newVal, oldVal) { this.basicMsg = '今年' + newVal + '岁' + ' ' + this.single; } } }); </script>
如上代码, 当我们在input
输入框中输入年龄后, 比如32
, 那么watch
就能对 'age'
这个属性进行监听,当值发生改变的时候, 就会把最新的计算结果赋值给 'basicMsg'
属性值, 因此最后在页面上就会显示 'basicMsg'
属性值了。
-
watch里面的
immediate
属性
如上watch
有一个特点是: 第一次初始化页面的时候, 是不会去执行age
这个属性监听的, 只有当age
值发生改变的时候才会执行监听计算. 因此我们上面第一次初始化页面的时候, 'basicMsg'
属性值默认为空字符串。那么我们现在想要第一次初始化页面的时候也希望它能够执行 'age'
进行监听, 最后能把结果返回给 'basicMsg'
值来。因此我们需要修改下我们的 watch
的方法,需要引入handler
方法和immediate
属性, 代码如下所示:
<div id="app"> <p>空智个人信息情况: {{ basicMsg }}</p> <p>空智今年的年龄: <input type="text" v-model="age" /></p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { basicMsg: '', age: 31, single: '单身' }, watch: { age: { handler(newVal, oldVal) { this.basicMsg = '今年' + newVal + '岁' + ' ' + this.single; }, immediate: true } } }); </script>
如上代码, 我们给我们的age
属性绑定了一个handler
方法。其实我们之前的watch
当中的方法默认就是这个handler
方法。但是在这里我们使用了immediate: true
; 属性,含义是: 如果在watch
里面声明了age
的话, 就会立即执行里面的handler
方法。如果 immediate
值为false
的话,那么效果就和之前的一样, 就不会立即执行handler
这个方法的。因此设置了 immediate:true
的话,第一次页面加载的时候也会执行该handler
函数的。即第一次 basicMsg
有值。
因此第一次页面初始化效果如下:
-
watch里面的
deep
属性
watch
里面有一个属性为deep
,含义是:是否深度监听某个对象的值, 该值默认为false
deep
实现机制是: 监听器会一层层的往下遍历, 给对象的所有属性都加上这个监听器。当然性能开销会非常大的。