写在前面
本文参考了官网以及其他博客的一些文章,加上自己的理解,感谢博主的分享
古话说的好,万事开头难,之前在开发项目过程中,一直不太理解watch的用法,知道后来用了几次,才稍稍有点理解,现在记录下来,方便后续学习更新和使用,也希望简友多多指教以及提出问题,大家互相学习。
一 首先说说 侦听器(watch),官网的解释
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
个人理解就是,当数据变化时想做某些操作,就可以用watch就好了。这样说可能比较模棱两可,还是举个栗子吧。
- 受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,
所以属性必须在 data 对象上存在才能让 Vue 转换它
,这样才能让它是响应的。
watch 可以监听数组,对象,字符串,
通过例子看看他们的而区别。
这是简单的一个监听
<template>
<div>
<p>changeNum: {{changeNum}}</p>
<p>watchNum: <input type="text" v-model="watchNum"></p>
还可以这么写
<input v-model="example1"/>
</div>
</template>
<script>
export default {
data() {
return {
watchNum: '张三',
otherNum: '丰',
changeNum: ' ',
example1:' ',
};
},
watch: {
//newVal是指更新后的数据
watchNum(newVal, oldVal) {
this.changeNum= newVal+ ' ' + this.otherNum;
},
example1:"exampleMethods",//值可以为methods的方法名
},
methods:{
exampleMethods(newVal,oldVal){
conosle.log(newVal,oldVal)
}
}
};
</script>
上面的代码的效果是,当我们输入watchNum后,wacth监听每次修改变化的新值,然后计算输出changeNum。
handler方法和immediate属性
上边的代码watch 的一个特点是,最初绑定的时候是不会执行的,要等到 watchNum改变时才执行监听计算。那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?我们需要修改一下我们的 watch 写法,修改过后的 watch 代码如下:
<script>
watch: {
//newVal是指更新后的数据
watchNum: {
handler(newVal, oldVal) {
this.changeNum = newVal + " " + this.otherNum;
},
// 代表在wacth里声明了watchNum这个方法之后立即先去执行handler方法
immediate: true
},
},
</script>
- 特别注意一下handler,我们给 watchNum绑定了一个handler方法,之前我们写的 watch 方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler
- immediate:true代表如果在 wacth 里声明了 watchNum之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
deep属性
- watch 里面还有一个属性 deep,默认值是 false,不监听,代表是否深度监听,如果是数组则不需要,
对象需要深度监听
<script>
watch: {
//newVal是指更新后的数据
watchNum: {
handler(newVal, oldVal) {
this.changeNum = newVal + " " + this.otherNum;
},
// 代表在wacth里声明了watchNum这个方法之后立即先去执行handler方法
immediate: true,
deep: true, //对象内部属性的监听,关键。
//deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器
},
},
</script>
二 然后在说说computed - 计算属性
的使用方法和理解
就想官网所说的那样,你在模版内做一些简单的运算还算比较好,但是运算比较多 的时候就很复杂,杂乱了。
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
然后这个时候你在使用计算属性,看看效果
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
- 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数
reversedMessage
。
你可以像绑定普通的属性一样在模版中绑定计算属性,接下来这段代码和话很重要,请仔细阅读,方便后边的理解。
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
当我们用计算属性来更新这两个变量时会好很多
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
看完上边的介绍不难发现两者的不同。
两者的共同之处
Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系.
看了上边的话应该明白为什么会有人说vue的侦听器和计算属性类似,是因为当你在做父子组件之间传值是已经改变了vm.message,所以计算属性的reversedMessage也会改变,就达到了更新数据的目的。
这也就是说两者在某些特定情况下都达到了获得新数据后改变数据的效果。
再看看两者的不同,特别注意红色字体部分
仔细的读完上边的分析,不难发现,两者还是有区别的
首先,watch - 侦听器 是被动的,他是监听到数据变化后才会触发watch,然后去更新数据,
这个时候你还发现,官网所说,当多个data中对象数据变化时,你就会写监听多个对象,就会很冗余
所以说watch比较适用与当一个对象变化来改变父组件或者子组件内多个对象或者条件的变化时
而computed是主动的,他是你主动去计算多个变量,改变他们之间的算法,以达到改变数据的目的,
然而呢数据的更新是需要触发重新渲染时
在上边提到过。
所以说computed更加适用于多个变量的改变引起某一个数据或对象的改变时
结束语
里边还有一些理解不足的地方,希望小伙伴多多指出。后期会不断更新。