vue3.0监听属性watch与watchEffect

watch监听

监听reactive定义的数据时
两个小坑:
1.监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
2.监视reactive定义的响应式数据中某个属性时:deep配置有效

 let sum1 = ref(0);
 let msg = ref("你好啊");
 let person = reactive({
   name: "张三",
   age: 18,
   job: {
     j1: { salary: 20 },
   },
 });
 const data = reactive({
   sum: "",
   name2: "",
 });
 
情况一: 监视ref所定义的响应式数据
 watch(
   sum1,
   (newValue, oldalue) => {
     console.log("sum1变化了",newValue, oldalue);
   },
   { immediate: true }
 );

情况二:监听ref所定义的多个响应式数据
watch([sum1, msg], (newValue, oldalue) => {
  console.log("sum1或msg变化了", newValue, oldalue);
});

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

情况四:监听reactive所定义的一个响应式数据中的某个属性,监听的数据要写成函数的形式将其返回
 watch(
   () => person.name,
   (newValue, oldalue) => {
     console.log("person的name变化了", newValue, oldalue);
   }
 );

情况五:监听reactive所定义的一个响应式数据中的某些属性,监听的数据要写成函数的形式将其返回
 watch([() => person.name, () => person.age], (newValue, oldalue) => {
   console.log("person的name或person的age变化了", newValue, oldalue);
 });

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

一般监听对象的话是没有办法正确的获取oldValue
watch监听的三个参数:
	第一个:监视的是谁,
	第二个:监视的回调,
	第三个:监视的配置

监听ref定义的数据时

let sum1 = ref(0);
let msg = ref("你好啊");
let person = ref({
  name: "张三",
  age: 18,
  job: {
    j1: { salary: 20 },
  },
});

因为sum1里面存的是基本属性类型的值,所以不用.value进行监听
watch(sum1, (newValue, oldValue) => {
  console.log("newValue", newValue);
  console.log("oldValue", oldValue);
});

watch监听的person.value 即监听的是RefImpl{......} 即RefImpl{......}的value实例对象
即监听的是Proxy

第一种方式
watch(person.value, (newValue, oldValue) => {
  console.log("newValue", newValue);
  console.log("oldValue", oldValue);
});

第二种方式
watch(
  person,
  (newValue, oldValue) => {
    console.log("newValue", newValue);
    console.log("oldValue", oldValue);
  },
  { deep: true }
);

watchEffect()函数
watchEffect()会立即执行一遍回调函数,如果这时函数产生了副作用,Vue 会自动追踪副作用的依赖关系,自动分析出响应源

<template>
    账号:<input type="text" v-model="account">
    <hr>
    员工薪资:<input type="number" v-model="emp.salary">
</template>
<script setup>
// 引入 watch 函数
import { reactive, ref, watchEffect } from 'vue'

// 账号
let account = ref('Abc')
// 员工
let emp = reactive({
    name: 'Jack',
    salary: 7000
})

// 创建成功后立即执行一遍
watchEffect(() => {
   // 此处用到了数据源,如果该数据源的值发生了变化,会重新执行该回调函数
   console.log('账号:' + account.value)
   console.log('员工的薪资:' + emp.salary)
})
</script>

回调的触发时机
默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用;这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
如果想在侦听器回调中能访问被 Vue 更新之后的DOM,你需要指明flush: ‘post’ 选项,或者你也可以使用更方便的别名watchPostEffect()函数

<script setup>
import { onMounted, reactive, ref, watchEffect, watchPostEffect } from 'vue'

// 账号
let account = ref('Abc')
// 密码
let password = ref('123456')
// 员工
let emp = reactive({
    name: 'Jack',
    salary: 7000
})

// 当视图渲染成功后
onMounted(() => {
   // 侦听账号
   watchEffect(() => {
       console.log('账号:' + account.value)
       // 默认情况下,回调触发机制:在 Dom 更新之前
       console.log(document.getElementById('titleAccount').innerHTML)
   })

   // 侦听密码
   watchEffect(
      () => {
          console.log('密码:' + password.value)
          // 默认情况下,回调函数触发机制:在 Dom 更新之前
          console.log(document.getElementById('titlePassword').innerHTML)
      },
      // 更改回调函数触发机制:在 Dom 更新之后
      { flush: 'post' }
   )

   // 侦听薪资
   watchPostEffect(() => {
      console.log('员工薪资:' + emp.salary)
      // 回调函数的触发机制:在 Dom 更新之后
      console.log(document.getElementById('titleSalary').innerHTML)
   })
})
</script>

watch和watchEffect的对比

watch

1. watch显式指定依赖数据,依赖数据更新时执行回调函数
2. 具有一定的惰性lazy 第一次页面展示的时候不会执行,只有数据变化的时候才会执行
(设置immediate: true时可以变为非惰性,页面首次加载就会执行)
3. 监视ref定义的响应式数据时可以获取到原值
4. 既要指明监视的属性,也要指明监视的回调

watchEffect

1. watchEffect自动收集依赖数据,依赖数据更新时重新执行自身
2. 立即执行,没有惰性,页面的首次加载就会执行
3. 无法获取到原值,只能得到变化后的值
4. 不用指明监视哪个属性,监视的回调中用到哪个属性就监视哪个属性

你可能感兴趣的:(javascript,前端,html)