在组合式API中,我们可以使用watch函数或者watchEffect函数在每次响应式状态发生变化时触发对应的回调函数。我们首先来看,怎么使用watch函数?
一、创建侦听器
语法:watch(source, callback, options)
1、source:需要侦听的数据源,可以是ref(包括计算属性)、一个响应式对象、一个 getter函数、或多个数据源组成的数组
2、callback:回调函数
a. 侦听单个数据源:回调函数的第一个参数为新值,第二个参数为旧值
b. 侦听多个数据源组成的数组:一个参数数组是新值,第二个参数数组是旧值
3、options:配置,Object类型
a. deep: true:深度侦听,一般用在侦听的是getter函数返回的对象
b. immediate: true:创建好侦听器立即执行
c. flush: 'post':更改回调的触发机制(Dom更新后)
实例1:侦听一个原始类型的数据
App.vue
<script setup>
import { ref,reactive,watch } from 'vue'
const account = ref('Abc')
const emp = reactive({
name: 'Jack',
salary: 7000
})
//侦听原始类型的数据变化
watch(account,(newVal,oldVal) => {
console.log("==========账号新旧值===========")
console.log(oldVal)
console.log(newVal)
console.log("===============================")
})
//侦听对象中的某一个属性变化(需要提供getter函数才可以)
//注意,你不能直接侦听响应式对象的属性值,这里需要用一个返回该属性的 getter 函数
watch(()=>emp.salary,(newVal,oldVal)=>{
console.log('===========员工薪资新旧值===========')
console.log(oldVal)
console.log(newVal)
console.log('====================================')
})
</script>
<!-- 视图区域(view) -->
<template>
账号:<input type="text" v-model="account">
<br>
<br>
员工薪资:<input type="number" v-model="emp.salary">
</template>
<style>
</style>
实例2:侦听一个对象类型的数据
App.vue
<script setup>
import { ref,reactive,watch } from 'vue'
let emp = reactive({
name: 'Jack',
salary: 7000
})
let dept = reactive({
id: '101',
name: '销售部'
})
let region = reactive({
id: '201',
name: '北美洲'
})
//侦听对象,直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发
//如果嵌套属性值发生变化,那么也会触发该回调函数,但是newVal,oldVal是相等的,因为它们是同一个对象
watch(emp,(newVal,oldVal) => {
console.log("==========员工信息新旧值===========")
console.log(oldVal)
console.log(newVal)
console.log("===============================")
})
//侦听:对象(getter)
//一个返回响应式对象的 getter 函数,只有在返回不同的对象时,才会触发回调
//所以下面的代码是无法触发该回调函数
watch(()=>dept,(newVal,oldVal) => {
console.log("=============部门信息新旧值=============")
console.log(oldVal)
console.log(newVal)
console.log("========================================")
})
//可以给上面这个例子显式地加上 deep 选项,强制转成深层侦听器,但是newVal,oldVal是相等的,因为它们是同一个对象
watch(()=>region,
(newVal,oldVal) => {
console.log("=============区域名称新旧值=============")
console.log(oldVal)
console.log(newVal)
console.log("========================================")
},
{deep: true}
)
</script>
<!-- 视图区域(view) -->
<template>
员工薪资:<input type="number" v-model="emp.salary">
<hr>
部门名称:<input type="text" v-model="dept.name">
<hr>
区域名称:<input type="text" v-model="region.name">
</template>
<style>
</style>
谨慎使用:深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。
实例3:侦听多个数据源组成的数组
App.vue
<script setup>
import { ref,reactive,watch } from 'vue'
let account = ref('Abc')
let emp = reactive({
name: 'Jack',
salary: 7000
})
let dept = reactive({
id: '101',
name: '销售部'
})
//侦听多个数据源组成的数组
watch([account,()=>emp.salary,dept],
([newAccount,newSalary,newDept],[oldAccount,oldSalary,oldDept]) =>{
console.log("=====账号新旧值=====")
console.log(newAccount)
console.log(oldAccount)
console.log("====================")
console.log("=====薪资新旧值=====")
console.log(newSalary)
console.log(oldSalary)
console.log("====================")
console.log("=====部门新旧值=====")
console.log(newDept)
console.log(oldDept)
console.log("====================")
})
</script>
<!-- 视图区域(view) -->
<template>
账号:<input type="text" v-model="account">
<hr>
员工薪资:<input type="number" v-model="emp.salary">
<hr>
部门名称:<input type="text" v-model="dept.name">
<hr>
</template>
<style>
</style>
实例4:侦听器配置选项
App.vue
<script setup>
import { ref,reactive,watch } from 'vue'
let account = ref('Abc')
let emp = reactive({
name: 'Jack',
salary: 7000
})
let password = ref('123456')
//创建完侦听器后立即执行一遍
watch(
account,
(newVal,oldVal) => {
console.log('账号变化:')
console.log(newVal)
console.log(oldVal)
console.log('==========')
},
{immediate:true}
)
//深度侦听,侦听函数返回的对象时,其嵌套属性值发生变化,依然可以触发回调函数,但是新旧值相等
watch(
()=>emp,
(newVal,oldVal) => {
console.log('员工变化:')
console.log(newVal)
console.log(oldVal)
console.log('==========')
},
{deep:true}
)
//更改回调函数的触发机制(Dom更新之后)
watch(
password,
(newVal,oldVal) => {
console.log('密码变化:')
console.log(newVal)
console.log(oldVal)
//默认情况下回调的触发机制在Dom更新之前执行
console.log(document.getElementById('titlePassword').innerHTML)
},
{flush: 'post'}
)
</script>
<!-- 视图区域(view) -->
<template>
账号:<input type="text" v-model="account">
<hr>
员工薪资:<input type="number" v-model="emp.salary">
<hr>
<h1 id="titlePassword">
密码:
<i>{{ password }}</i>
</h1>
密码:<input type="text" v-model="password">
<hr>
</template>
<style>
</style>
二、停止侦听器
调用watch()返回的函数即可
App.vue
<script setup>
import { ref,watch } from 'vue'
let account = ref('Abc')
let stopAccountWatch = watch(
account,
(newVal,oldVal) => {
console.log('账号变化:')
console.log(newVal)
console.log(oldVal)
console.log('==========')
}
)
</script>
<!-- 视图区域(view) -->
<template>
账号:<input type="text" v-model="account">
<hr>
<button @click="stopAccountWatch">停止账号侦听器</button>
</template>
<style>
</style>
1558

被折叠的 条评论
为什么被折叠?



