12 组合式API(三)
摘要:计算属性可以很好地帮助我们实时计算某个新数值,但在这个计算的过程中,我们希望在状态变化的时候执行一些其他的操作,这时候就需要用到侦听器。在本文的叙述中,我们会谈论在组合式中如何使用watch侦听器。
声明:为了文章的清爽性,在文章内部的代码演示中只会附上部分演示代码。
作者:来自ArimaMisaki创作
12.1 侦听ref对象
说明:组合式写法中的侦听器需要从vue包中解构出watch,其中watch为一个函数,详细的情况请参考下面的代码。
参数:watch
的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组;第二个参数即为回调函数,当数据发生改变时,应该做出的动作;第三个参数是配置对象,配置对象中可以有immediate属性
、deep属性
,这些我们在前面5.1.3都已经提及过。
提示:
- 当监视一个数据时,watch的第一个参数可以是一个ref对象;当我们监视多个ref对象时,如果不嫌麻烦可以使用多次watch函数,这是选项式写法不具备的,如果想要简便写法,可以将多个ref对象放入数组中传入,watch会监听数组中的每个元素。
- 当监视一个响应式的数据是对象时,若对象中还有一个对象作为属性,那么此时value是一个proxy对象,如果不加value想让监听器监听到其变化,需proxy对象的地址发生变化;如果想要监听到proxy对象属性发生变化,那么我们需要加value。
<script lang="ts" setup>
import {ref,reactive,watch} from 'vue'
let counter = ref(0)
function add(){
counter.value++
}
watch(counter,(newValue,oldValue)=>{
console.log(`counter变了,新值为${newValue},老值为${oldValue}`);
})
</script>
<template>
<div>
<h2>{{counter}}</h2>
<button @click="add">++1</button>
</div>
</template>
12.2 侦听reactive对象
说明:如果使用reactive定义一个响应式对象数据,那么通过Watch监听一个reactive对象是不能正确获取到oldValue的;当然,通过ref定义的响应式对象数据也不能被获取到oldValue,因为ref定义的响应式对象数据底层以reactive作为支撑;再者,ref定义的对象数据需要通过.value获取,而watch显然不具备此等操作。
提示:
- 通过reactive定义的响应式数据被强制开启了深度遍历,这种遍历是无法被关掉的。
- 如果想要监视响应式对象数据中的某个属性,必须采用
()=>对象.属性
的形式。 - 如果想要监视响应式对象数据中的某个对象属性中的属性 ,则必须开启deep配置,否则无法监视。
- 无论是监听ref对象,还是proxy对象,我们监听的都是对象,而非一个具体的值;故在监听的时候,我们的数据源不能是ref对象.value。
- 正是由于Vue3的watch侦听器有如此多的”突发情况“,这才导致了前端框架学习者们发出了“尤玉溪不懂Vue”的感慨。
12.3 watchEffect
说明:watchEffect函数是一个比较牛叉的功能,它从来不说自己监视谁,为此它的参数中并不需要指定数据源参数,只需直接给出一个回调函数;在该回调函数中你用到了哪个数据源,watchEffect就会监听到哪个数据源,无论数据源是否变化,watchEffect都会执行回调函数中的所有逻辑。
提示:watchEffect函数默认开启了immediate配置。
对比:watchEffectu有点像computed,但computed注重的是计算出来的值,所以必须要写返回值;而watchEffect更注重过程,所以不用写返回值。
<script lang="ts" setup>
import {ref,watchEffect} from 'vue'
let counter = ref(0)
function add(){
counter.value++
}
watchEffect(()=>{
const x = counter.value
console.log(`counter被改变`)
})
</script>
<template>
<div>
<h2>{{counter}}</h2>
<button @click="add">++1</button>
</div>
</template>