目录
💡 监听属性的概念
💡 watch有什么作用
💡 watch的基本语法
💡 监听属性的优缺点
💡 使用watch的场景
💡 监听属性的概念
在计算机科学中,watch是一种调试技术,用于监视程序运行时特定变量的值。当程序在调试器控制下执行时,调试器会显示变量的当前值,并在程序执行过程中自动更新该值。
在Vue中,watch 是一种用于监测数据变化并做出回应的技术。watch 可以监听任何一个数据属性,并在该属性发生变化时执行指定的函数。
💡 watch有什么作用
watch 可以监听数据的变化,并在数据变化时执行所指定的回调函数。它可以做以下几件事情:
✔ 监听数据变化:watch 可以监听 Vue 实例上的任何数据变化,包括简单数据类型、对象、数组和计算属性等。
✔ 接收新旧值:当数据发生变化时,watch 回调函数会接受到两个参数,分别是新值和旧值,这可以方便我们比较数据变化,进一步做出相应的处理。
✔ 执行响应函数:watch 的主要作用就是执行我们所指定的响应函数,以便我们对数据变化作出及时的响应,如重新计算、渲染视图或发送网络请求等。
✔ 深度监听:watch 还可以通过配置 deep 选项来深度监听嵌套对象的变化,这样当嵌套对象中的属性发生变化时也能捕获到。
✔ 立即执行:watch 还可以通过配置 immediate 选项来在初始化组件时立即执行回调函数,而不必等待数据变化。
✔ 取消监听:当一个 watch 监听器不再需要时,可以使用 unwatch 方法来取消监听。
综上所述,watch 可以监听数据变化并执行相应操作,这使得我们可以很方便地对数据变化做出处理和重新计算。在实际开发中,watch 经常被用来检测表单输入变化、监听状态变化以及优雅地处理异步操作等。
💡 watch的基本语法
// 对象式写法
watch: {
// 监听的属性名
属性名: {
handler: function (newVal, oldVal) {
// 对属性变化作出响应
}
}
}
// 函数式写法
watch: {
// 监听的属性名,参数为新旧值
'属性名'(newVal, oldVal) {
// 对属性变化作出响应
}
}
其中,handler 是一个函数,其第一个参数是属性的新值,第二个参数是属性的旧值。
属性名 是需要监听的属性名称。当属性发生变化时,watch 可以触发指定的响应函数来处理这个变化,比如,重新计算或发送请求等。
watch 可以监听对象、数组、计算属性等数据类型的变化,也可以通过 deep 选项来深度监听嵌套对象的变化,还可以使用 immediate 选项来立即执行回调函数。
通过示例来进一步了解监听属性
示例一:
new Vue({
data: {
message: 'Hello Vue!'
},
watch: {
// 当 `message` 属性发生变化时,执行 `handleMessageChange` 函数
message(newVal, oldVal) {
console.log('message changed from', oldVal, 'to', newVal);
}
},
methods: {
handleMessageChange(newVal, oldVal) {
console.log('message changed from', oldVal, 'to', newVal);
}
}
});
在上面的示例中,我们通过watch选项观察了message属性的变化。当message的值发生改变时,回调函数将会被触发,并输出新的值和旧的值。
除了直接在回调函数中执行逻辑外,还可以使用命名函数作为回调函数,或者使用箭头函数。此外,还可以在回调函数中返回一个值,以便在数据变化后执行其他操作。
除了观察数据的变化,watch选项还可以用于观察计算属性或方法。在这种情况下,回调函数将会在计算属性或方法的结果发生变化时被触发。
示例二:
<template>
<div>
<p>当前计数:{{ count }}</p>
<button @click="increment">+1</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
watch: {
count(newValue, oldValue) { // 监听 count 变化
console.log(`count 变化,新值为 ${newValue},旧值为 ${oldValue}`);
},
},
methods: {
increment() {
this.count++; // 改变 count 的值
},
},
};
</script>
上面的示例中,我们定义了一个 count 数据属性,并使用 watch 监听它的变化。在按钮点击事件中,我们改变了 count 的值,watch 监听到了数据的变化并执行了回调函数,输出了新旧值信息。
还可以通过配置 deep 和 immediate 选项来深度监听和在组件初始化时立即执行回调函数。
<script>
export default {
data() {
return {
person: {
name: 'Tom',
age: 18,
},
};
},
watch: {
'person.name'(newValue, oldValue) { // 深度监听 person.name 的变化
console.log(`person.name 变化,新值为 ${newValue},旧值为 ${oldValue}`);
},
},
created() {
this.$watch('person', (newValue, oldValue) => { // 深度监听 person 对象及其子属性的变化
console.log('person 变化', newValue, oldValue);
}, { deep: true });
this.$watch('person.name', (newValue, oldValue) => { // 初始化时立即执行回调函数
console.log(`person.name 变化,新值为 ${newValue},旧值为 ${oldValue}`);
}, { immediate: true });
},
};
</script>
或是
<script>
export default {
data() {
return {
person: {
name: 'Tom',
age: 18,
},
};
},
watch: {
'person.name':{
handler(newValue, oldValue) { // 深度监听 person.name 的变化
console.log(`person.name 变化,新值为 ${newValue},旧值为 ${oldValue}`);
},
// 当要监听对象/对象某个属性或数组、数组元素的时候需要添加deep:true属性
deep: true; // 深度监听 person 对象及其子属性的变化
// 如果想在第一次绑定的时候执行此监听函数 则需要设置immediate属性
immediate: true; // 初始化时立即执行回调函数
},
};
</script>
在这里,我们使用 watch 深度监听了 person.name 的变化,并在创建组件时使用 $watch 方法深度监听 person 对象的变化,同时设置了 immediate 选项,在初始化时立即执行回调函数。
参考:watch事件监听三种用法-CSDN博客 | watch监听事件的多种用法-ViewDesign
番外:vue - 组件中watch:{}监听与 this.$watch()的区别
💡 监听属性的优缺点
优点:
响应式:watch 可以实现数据的响应式监测,即在数据变化时自动执行回调函数,方便及时地对变化做出处理。
灵活性:watch 可以监听任意数据属性,并执行自定义的回调函数,使得我们可以根据具体需求做出相应的操作。
深度监听:watch 可以通过配置 deep 选项来深度监听嵌套对象的变化,不仅监听父级对象的变化,还能捕获到子级对象属性的变化。
初始化执行:watch 可以通过配置 immediate 选项在组件初始化时立即执行回调函数,而不必等待数据变化。
取消监听:当一个 watch 不再需要时,可以通过 unwatch 方法来取消监听,避免不必要的资源消耗。
缺点:
异步问题:watch 回调函数是异步执行的,在一些特定场景下,可能无法立即获取到最新的数据。如果需要立即获取到最新数据,可能需要配合 $nextTick 或使用计算属性来解决。
频繁触发:如果被监听的数据频繁变化,可能会导致 watch 回调函数被频繁触发,影响性能。此时,可以通过配置 immediate 选项和优化逻辑来减少不必要的回调触发。
复杂性:当使用多个 watch 监听多个数据时,可能会导致代码复杂度增加,维护起来稍显困难。在这种情况下,可以考虑使用计算属性来代替 watch。
那我们该怎么样去处理这些缺点呢?
✔ 处理异步问题:可以使用 $nextTick 方法来确保在更新视图之后再执行回调函数,以获取最新的数据。
watch: {
count: {
handler(newValue, oldValue) {
this.$nextTick(() => {
console.log(`count 变化,新值为 ${newValue},旧值为 ${oldValue}`);
// 在这里进行相应的操作
});
},
immediate: true,
},
}
✔ 优化频繁触发:如果被监听的数据频繁变化,可以考虑通过设置 immediate 选项或优化逻辑来减少不必要的回调触发。例如,可以使用 debounce 或 throttle 函数来限制回调函数的执行频率,以避免过多的触发。
✔ 简化复杂性:当使用多个 watch 监听多个数据时,可以考虑使用计算属性来代替 watch。计算属性具有自动的依赖跟踪和缓存机制,能够简化代码并提高性能。
computed: {
countInfo() {
return `当前计数:${this.count}`;
},
},
watch: {
countInfo(newValue, oldValue) {
console.log(`countInfo 变化,新值为 ${newValue},旧值为 ${oldValue}`);
},
},
这样,通过计算属性 countInfo 来监听 count 的变化,代码会更加清晰和易于维护。
综上所述,watch 提供了一种方便而强大的数据监测技术,但需要注意处理异步问题和频繁触发的情况,以及根据实际场景选择最佳的数据监听方式。
💡 使用watch的场景
数据监听:当数据发生变化时,可以使用 watch 来监听数据的变化,并在变化时执行相应的操作。例如,监听表单字段的变化,当表单字段发生变化时,可以根据新的值进行实时的验证、计算或发送请求等操作。
异步操作:当需要监听异步操作的结果或状态时,可以使用 watch 来监视异步操作的变化。例如,监视网络请求的结果,当请求返回时,可以根据返回的数据更新组件的状态或进行后续操作。
路由变化:当路由发生变化时,例如切换页面或参数变化,可以使用 watch 监听 $route 对象的变化,并根据新的路由信息进行相应的页面更新或数据加载操作。| Vue中监听路由参数变化的几种方式
深度监听对象或数组:当需要深度监听对象或数组内部属性的变化时,可以使用 watch 来进行深度监听。例如,监听一个复杂的数据结构,当其中某个属性发生变化时,可以触发相应的操作。
状态管理:当使用状态管理工具(如 Vuex)时,可以使用 watch 来监听状态的变化,并根据状态的变化进行相应的处理。例如,监听某个状态的变化,在状态变化时更新视图或触发其他操作。
总而言之,watch 适用于需要监听数据变化并执行相应操作的场景,特别是在需要处理异步操作、深度监听对象或数组、响应路由变化等情况下。
使用watch还需要注意的几个点:
1. 主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看作是 computed 和 methods 的结合体;
2. 可以监听的数据来源:data,props,computed内的数据;
3. watch支持异步;
4. 不支持缓存,监听的数据改变,直接会触发相应的操作;
5. 监听函数有两个参数,第一个参数是最新的值,第二个参数是输入之前的值,顺序一定是新值,旧值。
☀ 参考资料
vue2中watch(侦听器)讲解以及解决深度监听新值和旧值相同的两种方案(手写深拷贝和JSON.parse())
watch事件监听三种用法 | vue中watch如何对对象进行深度监听 | watch监听事件的多种用法