• vite+vue3+ts中watch和watchEffct的使用


    vite+vue3+ts中watch和watchEffct的使用

    watch

    vue官方文档:https://cn.vuejs.org/api/reactivity-core.html#watch
    可以监听基础类型,整个对象,对象的某个属性

    ref

    对于基本数据类型(如字符串、数字),ref 提供了完整的响应式特性

    对于对象,ref 也可以使其成为响应式,但 watch 默认不进行深度监听,需要手动指定 deep 选项

    ref基础类型:直接监听,可获取新旧值

    const num = ref(1);
    
    const changeValue = function () {
      num.value++;
    };
    
    watch(num, (newValue, oldValue) => {
      console.log("监听变化", newValue, oldValue);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ref对象类型:需要显式开启深度监听,但是只能获取新值

    需要使用深度监听,由于 JavaScript 对象和数组的引用特性,newValueoldValue 会指向相同的内存地址;因此,在数据变化后,newValueoldValue 是相同的

    const count = ref({
      a: 1,
      b: 2,
    });
    
    const changeValue = function () {
      count.value.a ++;
    };
    
    // 不生效
    watch(count, (newValue, oldValue) => {
      console.log("监听变化", newValue, oldValue);
    });
    // 生效,添加deep
    watch(count, (newValue, oldValue) => {
      console.log('监听变化deep', newValue, oldValue)
    }, { deep: true })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    把watch的引用类型数据源浅拷贝了一份,即可完成对新旧值得获取(多层数据需要使用深拷贝)

    watch(
      () => {
        return { ...count.value };
      },
      (newValue, oldValue) => {
        console.log("监听变化deep-return\n", newValue, oldValue);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • ref对象的单个属性

    此时第一个参数是一个箭头函数

    watch(() => count.value.a, (newValue, oldValue) => {
      console.log("监听变化ref单个\n", newValue, oldValue);
    });
    
    • 1
    • 2
    • 3
    • ref数组类型
    const list = ref([1, 2, 3, 4, 6]);
    
    const changeValue = function () {
      list.value[0] ++;
    };
    
    watch(
      list,
      (newValue, oldValue) => {
        console.log("监听变化list-deep\n", newValue, oldValue);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • ref对象数组类型
    const list = ref([
      { a: 1, b: 1 },
      { a: 1, b: 1 },
    ]);
    
    const changeValue = function () {
      list.value[0].a++;
    };
    
    watch(
      list,
      (newValue, oldValue) => {
        console.log("监听变化list-deep\n", newValue, oldValue);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用深拷贝获取旧值

    watch(
      () => JSON.parse(JSON.stringify(list.value)),
      (newValue, oldValue) => {
        console.log("监听变化deep-return\n", newValue, oldValue);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    reactive

    reactive 用于创建一个深层次的响应式对象

    对于 reactive 对象,watch 默认执行深度监听

    • reactive对象整体:直接监听,只能获取到新值
    const demo = reactive({
      name: "aaa",
      item: {
        name: "",
        num: 1,
      },
    });
    
    const changeValue = function () {
      demo.item.num++;
    };
    
    watch(demo, (newValue, oldValue) => {
      console.log("监听变化reactive\n", newValue, oldValue);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • reactive对象单个属性
    watch(() => demo.item.num, (newValue, oldValue) => {
      console.log("监听变化reactive单个\n", newValue, oldValue);
    });
    
    • 1
    • 2
    • 3
    props

    使用 getter 函数返回值的形式,默认不开启深度监听

    • 父组件
    <WatchB :item="demo"></WatchB>
    
    const demo = reactive({
      name: "aaa",
      num: 1,
      item: {
        name: "",
        num: 1,
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 子组件
    const props = defineProps(["item"]);
    
    const ite = ref();
    ite.value = props.item;
    
    watch(
      () => props.item,
      (newVal, oldVal) => {
        console.log(ite.value);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    immediate

    默认情况下watch懒加载的,设置immediate: true时,会在初始化时立即执行回调函数

    { deep: true, immediate: true }
    
    • 1
    组合监听

    在组合监听的情况下,Vue 需要明确知道是否需要对 reactive 对象进行深度监听,所以需要显式开启深度监听

    第一个参数是一个数组

    watch(
      [() => demo, num],
      ([newDemo, newNum], [oldDemo, oldNum]) => {
        console.log("watch 已触发: demo", newDemo, oldDemo);
        console.log("watch 已触发: num", newNum, oldNum);
      },
      { deep: true }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    watchEffect

    在 watchEffect 的回调中,任何访问的响应式引用都会被追踪,当这些引用的值发生变化时,watchEffect 的回调会自动重新执行

    watchEffect 适用于需要自动追踪多个数据源的场景,如副作用操作,用于清理或重置副作用(如定时器、订阅等)

    watchEffect默认初始时就会执行第一次,一旦运行就会立即监听,组件卸载的时候会停止监听

    watchEffect 无法获取到变化前的值,只能获取变化后的值

    vue官方文档:https://cn.vuejs.org/api/reactivity-core.html#watcheffect

    单值多值侦听
    const number = reactive({ count: 0 });
    
    const countAdd = () => {
      number.count++;
    };
    
    watchEffect(()=>{
      console.log("新的值:", number);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    watchEffect 本身不会进行深度监听,它只会自动跟踪其回调函数中所引用的响应式状态(通过 ref 或 reactive 创建的状态)的变化。如果在 watchEffect 中引用了一个 reactive 对象的某个属性,它只会在那个具体属性发生变化时触发

    const demo = reactive({
      name: "aaa",
      num: 1,
      item: {
        name: "",
        num: 1,
      },
    });
    
    watchEffect(() => {
      console.log("demo-num的变化后的值\n", demo.item.num);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    watchEffect 只会在 demo.item.num 发生变化时触发。对于 demodemo.num 的变化,watchEffect 不会响应,因为它没有被 watchEffect 的回调函数所引用

    watchEffect(() => {
      console.log("demo的变化后的值\n", demo);
    });
    
    • 1
    • 2
    • 3
    副作用
    // 副作用
    const v3 = ref(3)
    watchEffect(()=>{
      const v = v3.value
      // 存在异步
      setTimeout(()=>{
        console.log(v,'timeout')
      },1000);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    watchEffect(async onInvalidate=>{
      const v = v3.value
      // 存在异步
      const timeout = setTimeout(()=>{
        console.log(v,'timeout')
      },1000);
      onInvalidate(()=>{
        clearTimeout(timeout)
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    重复执行会触发 onInvalidate,取消上一次的异步请求

    停止监听
    const stop = watchEffect(() => {
      console.log("name:", demo.item.num);
    });
    
    const stopWatchEffect = () => {
      console.log("停止监听");
      stop();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    二分类资料的决策曲线DCA绘制
    Linux本地部署开源AI的PDF工具—Stirling PDF并实现公网随时访问
    读取txt文档并解析数据输出
    Java后端学习路线
    【LeetCode每日一题:808.分汤~~~边界条件的特判+记忆化搜索】
    MySQL入门第五天——数据表简单查询
    cloud的概念
    基于粒子群优化算法的UAV三维路径规划研究付Matlab代码
    关于是我的精灵问题还是代码还是动画的问题!
    12. 测试搭建百万并发项目
  • 原文地址:https://blog.csdn.net/qq_23858785/article/details/134464954