【Vue.js 3.0】Day-07 Composition API watch监听器 和 watchEffect高级监听器

目录

watch监听器

Vue2 中的 watch 回顾

Vue3 中的 watch 函数案例实现

Vue3 中的 watch 函数 value 的问题

Vue3 中的 watchEffect高级监听器

Vue3 中的 watchEffect函数案例实现

小结


watch监听器

  • 与Vue2.x中watch配置功能一致; 

  • 两个小“坑”:

    • 监听reactive定义的 响应式数据,会强制开启深度监听(deep:true),无法获取正确的oldvalue(变化前的值)。

    • 监听reactive定义的 响应式数据中的某个属性(对象形式) 时,不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果。

Vue2 中的 watch 回顾

  • Vue2 中只能有一个  watch 的配置项; 
  watch: {
    // 简单写法
    sum(newVal, oldVal) {
      console.log("sum的值发生改变", newVal, oldVal);
    },
    //  复杂写法
    sum: {
      immediate: true, // 立即监听
      deep: true, // 深度监听
      handler(newVal, oldVal) {
        console.log("sum的值发生改变", newVal, oldVal);
      },
    },
  },

Vue3 中的 watch 函数案例实现

<template>
  <h1>一个人的信息</h1>
  <h2>当前求和为: {{ sum }}</h2>
  <button @click="sum++">点我+1</button>
  <hr />
  <h2>当前数据: {{ msg }}</h2>
  <button @click="msg += '!'">修改msg信息</button>

  <hr />
  <h2>姓名: {{ person.name }}</h2>
  <h2>年龄: {{ person.age }}</h2>
  <h2>薪资: {{ person.job.j1.salary }} K</h2>
  <button @click="person.name += '~'">修改姓名</button>
  <button @click="person.age++">增长年龄</button>
  <button @click="person.job.j1.salary++">增长薪资</button>
</template>

<script>
import { ref, watch, reactive, watchEffect } from "vue";
export default {
  name: "Demo",

  setup() {
    let sum = ref(0);
    let msg = ref("你好啊");
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });
    // watch( 监视的属性, ()=>{ 监视的回调}, { 监视的配置 })

    /* 情况1: 监视ref所定义的一个响应式数据 */
    watch(sum, (newVal, oldVal) =>{
      console.log('sum变了', newVal, oldVal );
    })

    /* 情况2: 监视ref所定义的多个响应式数据, 在vue3中watch函数可以调用多次 */
    watch([sum, msg], (newVal, oldVal) => {
      console.log("sum或msg变了", newVal, oldVal);
    }, { immediate:true});

    /*
      情况3: 监听 reactive 所定义的一个响应式数据的全部属性; 
        1.注意: 此处无法正确的获取oldValue
        2.注意: 强制开启深度监听(deep配置无效 { deep:false })
    */
    watch(person, (newValue, oldValue) =>{
      console.log('person变化了', newValue, oldValue);
    },{ deep:false }) // 此处的deep配置是无效的


    /* 情况4:监听 reactive 所定义的一个响应式数据中的某个属性 */
    watch(() => person.age,(newValue, oldValue) => {
        console.log("person属性变化了", newValue, oldValue);
      }
    );


    /* 情况5:监听 reactive 所定义的一个响应式数据中的某些属性 */
    watch([() => person.name, () => person.age],(newValue, oldValue) => {
        console.log("person属性变化了", newValue, oldValue);
      }
    );

    /* 特殊情况 */
    watch(() => person.job,(newValue, oldValue) => {
        console.log("person属性变化了", newValue, oldValue);
      }, { deep: true} // 此处由于监视的是reactive所定义的对象中属性值是对象, 所以deep配置有效。
    );

    return {
      sum,
      msg,
      person,
    };
  },
};
</script>

Vue3 中的 watch 函数 value 的问题

<template>
  <h1>一个人的信息</h1>
  <h2>当前求和为: {{ sum }}</h2>
  <button @click="sum++">点我+1</button>
  <hr />
  <h2>当前数据: {{ msg }}</h2>
  <button @click="msg += '!'">修改msg信息</button>

  <hr />
  <h2>姓名: {{ person.name }}</h2>
  <h2>年龄: {{ person.age }}</h2>
  <h2>薪资: {{ person.job.j1.salary }} K</h2>
  <button @click="person.name += '~'">修改姓名</button>
  <button @click="person.age++">增长年龄</button>
  <button @click="person.job.j1.salary++">增长薪资</button>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  name: "Demo",
  setup() {
    let sum = ref(0);
    let msg = ref("你好啊");
    let person = ref({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });
    /*  Vue3中watch函数监听ref响应式数据value问题 */
    // 1.  watch 不能监听: sum.value, 而是能监听 ref 定义的 RefImpl 的数据结构!
    watch(sum, (newVal, oldVal) => {
      console.log(`sum的值发生改变`);
    });

    /*
        1.person 是一个 ref 定义的数据, person 的源数据是对象类型; 
        2.vue3 ref 定义对象的响应式数据,是求助reactive函数生成的; 
          2.1. 我们 person.value 获取proxy的对象, 直接获取监听(默认是深度监听)
          2.2. 设置 deep : true 开启深度监听 
    */
    watch(person.value, (newVal, oldVal) => {
      console.log(`person的值发生改变`);
    });
    
    // 不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果
    watch(person, (newVal, oldVal) => {
        console.log(`person的值发生改变`);
    },{ deep: true });

    return {
      sum,
      msg,
      person,
    };
  },
};
</script>

Vue3 中的 watchEffect高级监听器

watchEffect有点像computed:

  • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。

  • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。

  • watchEffect如果监听reactive定义的对象是不起作用的,只能监听对象中的属性。

Vue3 中的 watchEffect函数案例实现

<template>
  <h1>一个人的信息</h1>
  <h2>当前求和为: {{ sum }}</h2>
  <button @click="sum++">点我+1</button>
  <hr />
  <h2>当前数据: {{ msg }}</h2>
  <button @click="msg += '!'">修改msg信息</button>
  <hr />
  <h2>姓名: {{ person.name }}</h2>
  <h2>年龄: {{ person.age }}</h2>
  <h2>薪资: {{ person.job.j1.salary }} K</h2>
  <button @click="person.name += '~'">修改姓名</button>
  <button @click="person.age++">增长年龄</button>
  <button @click="person.job.j1.salary++">增长薪资</button>
</template>

<script>
import { ref, watch, reactive, watchEffect } from "vue";
export default {
  name: "Demo",
  setup() {
    let sum = ref(0);
    let msg = ref("你好啊");
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });
    //watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
    watchEffect((before) => {
      console.log("触发了watchEffect");
      console.log(`修改后的值为:${sum.value} ${msg.value} ${person.name}`);
      // 默认修改后不执行, 触发修改后优先执行 
      before(() => {
        console.log("先执行的 before 回调");
      });
    });

    return {
      sum,
      msg,
      person,
    };
  },
};
</script>

小结

  • watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行(忽略watch第三个参数的配置,如果修改配置项也可以实现立即执行)
  • watch需要传递监听的对象,watchEffect不需要
  • watch只能监听响应式数据:ref定义的属性和reactive定义的对象,如果直接监听reactive定义对象中的属性是不允许的(会报警告),除非使用函数转换一下。其实就是官网上说的监听一个getter
  • watchEffect如果监听reactive定义的对象是不起作用的,只能监听对象中的属性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值