1.watch

计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。

在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数.

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

1.侦听数据源类型

watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组.

  • 两个小“坑”:

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

2.demo

<template>
  <div>
    <h3>watch和watchEffect</h3>

  <input type="text" v-model="bir" placeHolder="请输入出生年月"  >
  <p>当前的周岁年龄为:{{age}}</p>
  <input type="text" v-model="firstName" >+
  <input type="text" v-model="lastName">=
  <input type="text" v-model="fullName">

  <input type="text" v-model="people.name">
  <input type="text" v-model="people.age">
  <input type="text" v-model="people.job.salary">
  </div>
</template>
<script setup>
import {ref,watch,reactive,watchEffect} from "vue"
const bir=ref("2018/5/20");
const age=ref(0);

//1.watch监听单个ref数据
watch(bir,(newValue,oldValue)=>{
  console.log("监听到了txt的变化")
  console.log(newValue,oldValue);
  age.value=new Date().getFullYear()-new Date(bir.value).getFullYear();
})
//2.监视多个ref定义的响应式数据
const firstName=ref("张");
const lastName=ref("三");
const fullName=ref("张三")
/**
 watch([firstName,lastName],(newValue,oldValue)=>{
   console.log(newValue,oldValue)
   //newValue:[第一个监听数据的最新值,第二个监听数据的最新值,....]
   //oldValue:[第一个监听数据的上一次操作的值,第二个监听数据的上一次操作的值,....]
   fullName.value=newValue[0]+newValue[1];
 })
 **/
watchEffect(()=>{
  fullName.value=firstName.value+lastName.value
})
//3.监视reactive定义的响应式数据
// 若watch监视的是reactive定义的响应式数据,则无法正确获得        oldValue!!
// 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视 
const people=reactive({
  name:'张三',
  age:13,
  job:{
    address:'中山西路',
    salary:"40k"
  }
})
/**
 watch(people,(newValue,oldValue)=>{
   console.log("监听people对象");
   console.log(newValue,oldValue);
 },{deep:false})//此处的deep配置不再奏效
**/
//4.监视reactive定义的响应式数据中的某个属性

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

//5.监视reactive定义的响应式数据中的某些属性
//这时newValue,oldValue又可以正常使用了
watch([()=>people.name,()=>people.age],(newValue,oldValue)=>{
    console.log('person的name变化了',newValue,oldValue)
},{immediate:true,deep:true})
</script>

2.watchEffect函数

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。

  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。

  • watchEffect有点像computed:

    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
    • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

3.watch vs. watchEffect

watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:

watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。

watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。

文档更新时间: 2023-08-11 15:15   作者:董老师