watch
是 vue 中常用的监听器,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作。
Vue官网很明确的建议我们这样使用watch侦听属性:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
watch: {
监听的属性: {
handler(数据改变后新的值, 数据改变前旧的值) {
编写处理逻辑
}
}
}
<template>
<div>
<div>
<input type="text" v-model="something">
</div>
</div>
</template>
<script>
export default {
data() {
return {
something: ""
}
},
watch: {
"something": {
handler(newVal, oldVal) {
console.log("新的值:" + newVal);
console.log("旧的值:" + oldVal);
console.log("hellow world");
}
}
}
}
</script>
输入框中输入1、2 , 效果图如下:
还可以 简写 如下:
watch: {
"something"(newVal, oldVal) {
console.log("新的值:" + newVal);
console.log("旧的值:" + oldVal);
console.log("hellow world");
}
}
<template>
<div>
<div>
<input type="text" v-model="obj.field1">
</div>
</div>
</template>
<script>
export default {
data() {
return {
something: "",
obj: {
field1: "",
field2: ""
}
}
},
watch: {
"obj.field1"(newVal, oldVal) {
console.log("新的值:" + newVal);
console.log("旧的值:" + oldVal);
console.log("hellow world");
}
}
}
</script>
输入框中输入1、2 , 效果图如下:
当需要监听一个对象的变化时,普通的 watch 方法无法监听到对象内部属性的变化,可以设置深度监听 deep: true
,当对象的属性较多时,每个属性的变化都会执行 handler。
<template>
<div>
<div>
<input type="text" v-model="obj.field1">
</div>
</div>
</template>
<script>
import { stringifyQuery } from "vue-router";
export default {
data() {
return {
something: "",
obj: {
field1: "",
field2: ""
}
}
},
watch: {
"obj": {
handler(newVal, oldVal) {
console.log("新的值:" + newVal);
console.log("旧的值:" + oldVal);
console.log("hellow world");
},
deep: true
}
}
}
</script>
输入框中输入1、2 , 效果图如下:
vue 中用 console.log
直接打印对象显示 [object Object]
,使用 console.log(JSON.stringify(obj))
,能把对象以 json 格式输出。
watch: {
"obj": {
handler(newVal, oldVal) {
console.log("新的值:" + JSON.stringify(newVal));
console.log("旧的值:" + JSON.stringify(oldVal));
console.log("hellow world");
},
deep: true
}
}
⚠️但是,结果发现旧的值和新的值一样,为什么呢?
对于引用类型,赋值指向是地址,地址指向堆区存储的值,所以新旧值一样,换句话说就是指向堆的同一个空间,拷贝的是地址,值也是跟着变的,一旦改变拷贝对象中某个变量的值 原始对象也会被改变;
✨解决方案:
利用深拷贝,会创建出一个新的地址指向新的空间。属性发生改变时,跟原始对象值互不干扰(这里运用了
computed
计算属性的暂缓特性来赋值)
<template>
<div>
<div>
<input type="text" v-model="obj.field1">
</div>
</div>
</template>
<script>
export default {
data() {
return {
something: "",
obj: {
field1: "",
field2: ""
}
}
},
computed: {
newObj() {
return JSON.stringify(this.obj);
}
},
watch: {
"newObj": {
handler(newVal, oldVal) {
console.log("新的值:" + JSON.stringify(newVal));
console.log("旧的值:" + JSON.stringify(oldVal));
console.log("hellow world");
},
deep: true
}
}
}
</script>
immediate
设置为 true,页面进来就会立即执行监听。
watch: {
"newObj": {
handler(newVal, oldVal) {
console.log("新的值:" + JSON.stringify(newVal));
console.log("旧的值:" + JSON.stringify(oldVal));
console.log("hellow world");
},
deep: true,
immediate: true
}
}
进入页面,立即执行监听。
VUE2 代码:
watch: {
nums () {},
'demo.name' () {}
}
VUE3 代码:
watch(nums, () => {})
watch(() => demo.name, () => {})
详细参考:
VUE3 中的 Watch 详解