Vue3 watch详解

554 阅读2分钟

一、watch的几种情况

1、watch一个ref变量,基本数据类型和对象类型都可以,但需要注意的是,传入对象类型的数据源时,默认情况,监听的是整个对象的引用有没有发生改变,而不是对象中的某个属性(在不使用deep配置项时)

import {ref, watch} from 'vue'
const a = ref(0);
// 第一个参数是要监听的对象(不需要.value),第二个参数是回调(第一个参数是新值, 第二个参数是旧值)
watch(a, (newValue, oldValue) => {
    console.log(newValue, oldValue)
})

2、watch一个reactive变量,需要注意监听整个对象和监听对象的某个属性是不一样的,

如果直接传递一个对象,那么默认情况下,对象中任意属性的变化都会被监听到

<script setup>
import { watch, ref, reactive } from 'vue';

const obj = reactive({
  name: '张三',
  age: 18
})
watch(obj, (oldValue, newValue) => {
  console.log(oldValue, newValue);
})
</script>

<template>
    <div>
      {{ obj }}<br>
      <button @click="obj.age++">Click</button>
    </div>
</template>

<style scoped>
</style>

如果只想监听某个属性的话,则需要传入一个getter函数(这个getter函数具体是什么意思暂时还不太明确,现在的理解就是一个返回要监听的属性的函数),如下所示:

<script setup>
import { watch, reactive } from 'vue';

const obj = reactive({
  name: '张三',
  age: 18
})
watch(() => obj.age, (oldValue, newValue) => {
  console.log(oldValue, newValue);
})
</script>

<template>
    <div>
      {{ obj }}<br>
      <button @click="obj.age++">Click</button>
    </div>
</template>

<style scoped>
</style>

watch还有第三个参数,就是一个配置对象,其中有两个常用的属性:

  • immediate,创建监听器时是否需要立即执行一次
  • deep,是否要对某个对象进行深度监听

还有其他形式的watch,暂时不写,因为还没咋用过。

二、watchEffect()

如果我们想在监听的数据发生变化时做一些事情,例如发送请求等(vue和react都把这种操作称之为副作用,不太理解),我们可能需要这样写:

import {reactive, watch} from 'react'
import {queryData} from 'api/user'
 const requestParam = {
     pageIndex:1,
     pageSize:10
 }
 watch(() => requestParam.pageIndex), async (newIndex, oldIndex) => {
     const result = await queryData(newIndex);
 })

vue提供了一个比较简洁的api来实现相同的功能,那就是watchEffect,无需传递依赖的数据源,并且会自动追踪入参函数中涉及到的数据源,并在数据源改变时触发回调函数,如下所示,当pageIndex和pageSize中的任意一个发生变化时,都会触发回调函数,并且当组件第一次加载完时,会立即触发

import {reactive, watchEffect} from 'react'
import {queryData} from 'api/user'
 const requestParam = {
     pageIndex:1,
     pageSize:10
 }
 watchEffect(async () => {
     const result = await queryData(requestParam.pageIndex, requestParam.pageSize);
 })