vue3.0 watch监听

本文详细介绍了Vue2.x和Vue3.0中的watch函数用法,包括单个ref、多个ref的监听,以及针对reactive对象的注意事项,深度探讨了配置immediate和deep的区别,帮助开发者理解响应式编程的精髓。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue2.x watch

vue2.x watch

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
</template>

<script>
import { ref } from "vue";
export default {
  // vue2.x 简易写法
  watch: {
    sum(newval, oldval) {
      console.log(newval, oldval);
    },
  },
  setup() {
    const sum = ref(0);
    return {
      sum,
    };
  },
};
</script>

正常打印,说明vue3中也可以使用vue2.x的写法
在这里插入图片描述
完整写法就是带有配置项的

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
</template>

<script>
import { ref } from "vue";
export default {
  // vue2.x 简易写法
  // watch: {
  //   sum(newval, oldval) {
  //     console.log(newval, oldval);
  //   },
  // },
  watch: {
    sum: {
      immediate:true, // 立即执行一次
      deep:true,// 深度监听
      handler(ewval, oldval) {
        console.log(newval, oldval);
      },
    },
  },
  setup() {
    const sum = ref(0);
    return {
      sum,
    };
  },
};
</script>

vue3.0 watch

监听ref和多个ref

vue3中的watch是一个函数,所以需要单独引入

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const sum = ref(0);
    // 是一种行为 所以没有返回
    watch(sum, (newval, oldval) => {
      console.log("vue3.0", newval, oldval);  
    });
    return {
      sum,
    };
  },
};
</script>

在这里插入图片描述
以上演示了监听单个ref响应式数据,现在演示监听多个,比较简单的写法就是用两个watch

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
  <hr />
  <h2>招呼:{{ info }}</h2>
  <button @click="info += '!'">打招呼</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const sum = ref(0);
    const info = ref("hello");
    // 1.监听ref单个响应式数据
    watch(sum, (newval, oldval) => {
      console.log("求和", newval, oldval);
    });
    // 2.监听多个响应式数据 在vue2.x中watch是个配置项,所以只能写一个watch,vue3.0中是函数,可以写多个
    watch(info, (newval, oldval) => {
      console.log("招呼:", newval, oldval);
    });
    return {
      sum,
      info,
    };
  },
};
</script>

在这里插入图片描述

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
  <hr />
  <h2>招呼:{{ info }}</h2>
  <button @click="info += '!'">打招呼</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const sum = ref(0);
    const info = ref("hello");
    // 1.监听ref单个响应式数据
    // watch(sum, (newval, oldval) => {
    //   console.log("求和", newval, oldval);
    // });
    // 2.监听多个响应式数据 在vue2.x中watch是个配置项,所以只能写一个watch,vue3.0中是函数,可以写多个
    watch([sum, info], (newval, oldval) => {
      console.log("新值newval", newval);
      console.log("旧值oldval", oldval);
    });
    return {
      sum,
      info,
    };
  },
};
</script>

在这里插入图片描述
immediate,deep配置如下,

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
  <hr />
  <h2>招呼:{{ info }}</h2>
  <button @click="info += '!'">打招呼</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const sum = ref(0);
    const info = ref("hello");
    // 1.监听ref单个响应式数据
    watch(
      // 第一个参数,监视的数据
      sum,
      // 第二个参数,监视的回调
      (newval, oldval) => {
        console.log("求和", newval, oldval);
      },
      // 第三个参数,监视的配置
      { immediate: true}
    );
    // 2.监听多个响应式数据 在vue2.x中watch是个配置项,所以只能写一个watch,vue3.0中是函数,可以写多个
    // watch([sum, info], (newval, oldval) => {
    //   console.log("新值newval", newval);
    //   console.log("旧值oldval", oldval);
    // });
    return {
      sum,
      info,
    };
  },
};
</script>

在这里插入图片描述

监听ref注意点

不需要.value(会报错),因为需要watch监听一个保存数据的响应式reflmpl对象结构,并不是一个.value的静态属性

<template>
  <h2>求和:{{ sum }}</h2>
  <button @click="sum++">++</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const sum = ref(0);
    watch(sum.value, (newval, oldval) => {
      console.log("求和", newval, oldval);
    });
    return {
      sum,
    };
  },
};
</script>

在这里插入图片描述
另外在ref监听对象类型时,是需要加上.value的,因为(比如说peson)对象是被reflmpl所包裹的对象

<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <p>工资:{{ person.job.salary.current }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.job.salary.current++">++工资</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  setup() {
    const person = ref({
      name: "张三",
      age: 18,
      job: {
        salary: {
          current: 20,
        },
      },
    });
    console.log("person", person);
    watch(
      person,
      (newval, oldval) => {
        console.log("newval", newval);
        console.log("oldval", oldval);
      },
    );
    return {
      person,
    };
  },
};
</script>

监听person仅仅只是监听了Reflmpl中的变化,并不能监听到.value,也就是Proxy中的变化(因为内存地址没有发生改变,需要Proxy中的属性内存发生改变才能够监听到)
在这里插入图片描述

监听reatcive的坑

监听reactive数据
如果watch监听reactive响应式数据的话,会有点坑。演示代码和打印如下

<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      name: "张三",
      age: 18,
    });
    // 1.监听ref单个响应式数据
    watch(person, (newval, oldval) => {
      console.log("newval", newval);
      console.log("oldval", oldval);
      console.log("数据监听");
    });
    return {
      person,
    };
  },
};
</script>

在这里插入图片描述
通过打印可以发现,watch无法正确获取oldval的数据(ref定义的对象也不行,因为ref定义的对象本质上还是通过reactive转为响应式)。
另外,相比于vue2.x,vue3.0的监听对象如果是reactive对象,会强制开启deep深度监听。

<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <p>工资:{{ person.job.salary }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.job.salary++">++工资</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      name: "张三",
      age: 18,
      job: {
        salary: 20,
      },
    });
    // 1.监听ref单个响应式数据
    watch(person, (newval, oldval) => {
      console.log("newval", newval);
      console.log("oldval", oldval);
      console.log("数据监听");
    });
    return {
      person,
    };
  },
};
</script>

在这里插入图片描述
是不需要开启deep的,并且deep为false也无效。

reactive 中的某个属性

如果要监听reactive中某个属性值时,需要写成函数

<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <p>工资:{{ person.job.salary }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.job.salary++">++工资</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      name: "张三",
      age: 18,
      job: {
        salary: 20,
      },
    });
    // 1.监听reactive中某个属性
    watch(
      () => person.age,
      (newval, oldval) => {
        console.log("newval", newval);
        console.log("oldval", oldval);
        console.log("数据监听");
      }
    );
    return {
      person,
    };
  },
};
</script>

在这里插入图片描述

监听reactive中某些属性

在这里插入代码片
<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <p>工资:{{ person.job.salary }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.job.salary++">++工资</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      name: "张三",
      age: 18,
      job: {
        salary: 20,
      },
    });
    // 1.监听reactive中某些属性
    watch([() => person.name, () => person.age], (newval, oldval) => {
      console.log("newval", newval);
      console.log("oldval", oldval);
      console.log("数据监听");
    });
    return {
      person,
    };
  },
};
</script>

在这里插入图片描述

特殊情况 监听reactive中的对象

监听reactive中的对象是要加上deep的

<template>
  <h2>个人信息</h2>
  <p>姓名:{{ person.name }}</p>
  <p>姓名:{{ person.age }}</p>
  <p>工资:{{ person.job.salary.current }}</p>
  <button @click="person.age++">++</button>
  <button @click="person.job.salary.current++">++工资</button>
  <button @click="person.name += '!'">打招呼</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    const person = reactive({
      name: "张三",
      age: 18,
      job: {
        salary: {
          current: 20,
        },
      },
    });
    // 1.监听reactive中某些属性
    watch(
      () => person.job,
      (newval, oldval) => {
        console.log("newval", newval);
        console.log("oldval", oldval);
        console.log("数据监听");
      },
      { deep: true }
    );
    return {
      person,
    };
  },
};
</script>

在这里插入图片描述

总结

1、监听普通ref属性,可配置immediate,不需要配置deep,因为ref定义基本数据类型。
2、监听reactive定义的一个响应式对象的所有属性,如果是直接监听person,也就是代理数据,那是不需要deep的,因为deep是强制开启的,并且oldval是无法正确获取,
3、监听reactive定义的响应式数据中某个属性时,要写成函数。
4、监听reactive定义的响应式数据中多个属性时,写成函数数组。
5、监听reactive定义的响应式数据中的一个对象中的属性,要加deep。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值