目录
前言:
今天给大家讲解的是vue3.0中watch侦听器的使用及语法,看完文章希望能够帮助到你!
1.选项式 API 中的侦听器
在选项式 API 中,我们可以使用watch选项在每次响应式属性发生变化时触发一个函数
1.1函数式侦听器
- 在watch选项中声明的函数即为函数式侦听器,其中函数名就是要侦听的数据源,函数中的参数1为新数据值,参数2为旧数据值
<script>
export default {
data: () => ({
age: 30, // 年龄
emp: {
name: 'Jack', // 名字
salary: 7000 // 薪水
}
}),
// 侦听器
watch: {
/**
* 侦听 age 数据源是否发生变化
* @param {*} newData 新值
* @param {*} oldData 旧值
*/
age(newData, oldData) {
console.log('newData: ' + newData)
console.log('oldData: ' + oldData)
},
/**
* 侦听 emp.name 数据源是否发生变化(通过采用字符串路径的形式来侦听对象中的某一个属性)
* @param {*} newData 新值
* @param {*} oldData 旧值
*/
'emp.name'(newData, oldData) {
console.log('newData: ' + newData)
console.log('oldData: ' + oldData)
}
}
}
</script>
<template>
年龄:<input type="number" v-model="age">
<hr>
员工的名字:<input type="text" v-model="emp.name">
</template>
1.2对象式侦听器
- 在watch选项中声明的对象即为对象式侦听器,对象名就是要侦听的数据源,其中对象里的handler函数为数据源发生变化后需要执行的代码块,其参数1为新数据值,参数2为旧数据值
<script>
export default {
data: () => ({
age: 30, // 年龄
emp: {
name: 'Jack', // 名字
salary: 7000 // 薪水
}
}),
// 侦听器
watch: {
// 侦听 age 数据源
age: {
/**
* 如果 age 数据源发生变化,将执行handler的代码片段
* @param {*} newData 新值
* @param {*} oldData 旧值
*/
handler(newData, oldData) {
console.log('newData: ' + newData)
console.log('oldData: ' + oldData)
}
},
// 侦听 emp.name 数据源
'emp.name': {
/**
* 如果 emp.name 数据源发生变化,将执行handler的代码片段
* @param {*} newData 新值
* @param {*} oldData 旧值
*/
handler(newData, oldData) {
console.log('newData: ' + newData)
console.log('oldData: ' + oldData)
}
}
}
}
</script>
<template>
年龄:<input type="number" v-model="age">
<hr>
员工的名字:<input type="text" v-model="emp.name">
</template>
1.3对象式侦听器相关参数
1.3.1deep
watch默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数,而嵌套属性的变化不会触发
如果想侦听所有嵌套的变更,你需要深层侦听器deep: true选项
深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大
watch: {
// 侦听 emp 对象数据源
emp: {
// 默认的浅层次的侦听器:只有侦听的数据源的值发生变化时,才会触发 handler 函数,而改变侦听的数据源中的嵌套属性值并不会出发该函数
handler(newData, oldData) {
console.log('员工的新旧值:')
console.log(newData)
console.log(oldData)
}
},
student: {
deep: true, // 深度侦听:如果改变侦听对象中的嵌套属性值,也会触发 handler 函数,但是 newData 和 oldData 是相等的
// 只有改变侦听对象的值时,newData 和 oldData 才是不相等的
handler(newData, oldData) {
console.log('学生的新旧值:')
console.log(newData)
console.log(oldData)
}
}
},;
1.3.2immediate
watch 默认是懒执行的:仅当数据源变化时,才会执行回调;但在某些场景中,我们希望在创建侦听器时,
立即执行一遍回调,可采用immediate: true选项
watch: {
account: {
// 默认形况下,侦听器懒执行的:仅当数据源变化时,才会执行回调
handler(newData, oldData) {
console.log('账号的新旧值:')
console.log(newData)
console.log(oldData)
}
},
student: {
deep: true,
immediate: true, // 创建侦听器时立即执行一次该 handler 函数
handler(newData, oldData) {
console.log('学生的新旧值:')
console.log(newData)
console.log(oldData)
}
}
}
1.3.3flush
默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用;这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
如果想在侦听器回调中能访问被 Vue 更新之后的DOM,你需要指明flush: 'post’选项
watch: {
account: {
handler(newData, oldData) {
console.log('账号的新旧值:')
console.log(newData)
console.log(oldData)
// 侦听器默认情况下,回调函数中访问 Dom 将是更新之前的状态
console.log(document.getElementById('titleAccount').innerHTML)
}
},
password: {
flush: 'post', // 更改回调的触发机制(Dom 更新后)
handler(newData, oldData) {
console.log('密码的新旧值:')
console.log(newData)
console.log(oldData)
// 回调函数中访问 Dom 将是更新之后的状态
console.log(document.getElementById('titlePassword').innerHTML)
}
}
}
1.4this.$watch 侦听器
1.4.1 创建侦听
使用组件实例的 $watch()方法来命令式地创建一个侦听器;它还允许你提前停止该侦听器
语法:this.$watch(data, method, object)
1. data:侦听的数据源,类型为String
2. method:回调函数,参数一新值,参数二旧值
3. object:配置
a. deep:深度侦听
b. immediate:创建时立即触发
c. flush: 'post':更改回调机制(DOM更新后)
<script>
export default {
data: () => ({
account: 'Abc', // 账号
emp: {
name: 'Jack', // 名字
salary: 7000 // 薪资
},
student: {
name: 'Annie', // 名字
age: 18 // 年龄
}
}),
// 声明周期函数:页面成功渲染后
mounted() {
// 通过组件的实例调用$watch函数来创建侦听器
// 语法:this.$watch(data, method, object)
// 1. data:侦听的数据源,类型为String
// 2. method:回调函数,参数一新值,参数二旧值
// 3. object:配置
// a. deep:深度侦听
// b. immediate:创建时立即触发
// c. flush: 'post':更改回调机制(DOM更新后)
this.$watch('account', (newData, oldData) => {
console.log('账号的新旧值:')
console.log(newData)
console.log(oldData)
})
this.$watch('emp.salary', (newData, oldData) => {
console.log('薪资的新旧值:')
console.log(newData)
console.log(oldData)
}, {
immediate: true })
this.$watch('student', (newData, oldData) => {
console.log('学生的新旧值:')
console.log(newData)
console.log(oldData)
console.log(document.getElementById('titleAge').innerHTML)
}, {
deep: true, flush: 'post' })
}
}
</script>
<template>
账号:<input type="text" v-model="account">
<hr>
薪资:<input type="numner" v-model="emp.salary">
<hr>
<h3 id="titleAge">
学生年龄:<span>{
{
student.age }}</span>
</h3>
学生年龄:<input type="numner" v-model="student.age">
</template>
1.4.2 停止侦听
需要自行停止侦听器,这时可以调用$watch() API 返回的函数
<script>
export default {
data: () => ({
account: 'Abc', // 账号
stopAccountWatch: null // 调用该函数,可以停止侦听账号数据源
}),
// 声明周期函数:页面成功渲染后
mounted() {
this.stopAccountWatch = this.$watch('account', (newData, oldData) => {
console.log('账号的新旧值:')
console.log(newData)
console.log(oldData)
})
}
}
</script>
<template>
账号:<input type="text" v-model="account">
<button @click="stopAccountWatch">停止侦听账号数据源</button>
</template>';
2.组合式 API 中的侦听器
在组合式API中,我们可以使用watch函数或者watchEffect函数在每次响应式状态发生变化时触发对应的回调函数
2.1 watch()函数
2.1.1创建侦听
语法: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更新后)
<script setup>
// 引入 watch 函数
import {
ref, reactive, watch } from 'vue'
// 账号
let account = ref('Abc')
// 员工
let emp = reactive({
name: 'Jack',
salary: 7000
})
// 密码
let password = ref('123456')
// 侦听:创建完侦听器后立即执行一边
watch(
account,
(newData, oldData) => {
console.log('===== 账号 =====')
console.log(newData)
console.log(oldData)
},
// 创建完侦听器后立即执行一边
{
immediate: true }
)
// deep: true:深度侦听,侦听函数返回的对象时,其嵌套属性值发生变换,依然可以触发回调函数,但是 newData, oldData 是相等的
watch(
() => emp,
(newData, oldData) => {
console.log('===== 员工 =====')
console.log(newData)
console.log(oldData)
},
// 深度侦听
{
deep: true }
)
watch(
password,
(newData, oldData) => {
console.log('===== 密码 =====')
console.log(newData)
console.log(oldData)
// 默认情况下回调的触发机制在Dom更新之前执行
console.log(document.getElementById('titlePassword').innerHTML)
},
// 更改回调函数的触发机制(Dom更新之后)
{
flush: 'post' }
)
// 侦听:多个数据源组成的数组
watch(
// 侦听多个数据源组成的数组
[account, () => emp.salary, dept],
// 参数一:新值数组,参数二:旧值数组
([newAccount, newSalary, newDept], [oldAccount, oldSalary, oldDept]) => {
console.log('===== 账号新旧值 =====')
console.log(newAccount)
console.log(oldAccount)
console.log('===== 薪资新旧值 =====')
console.log(newSalary)
console.log(oldSalary)
console.log('===== 部门新旧值 =====')
console.log(newDept)
console.log(oldDept)
}
)
</script>
<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="password" v-model="password">
</template>
2.1.2 停止侦听
停止侦听器:调用watch()返回的函数即可
<script setup>
// 引入 watch 函数
import {
ref, watch } from 'vue'
// 账号
let account = ref('Abc')
// 停止侦听器:调用 watch 返回的函数即可
let stopAccountWatch = watch(
account,
(newData, oldData) => {
console.log('===== 账号 =====')
console.log(newData)
console.log(oldData)
}
)
</script>
<template>
账号:<input type="text" v-model="account">
<button @click="stopAccountWatch">停止账号侦听器</button>
</template>
2.2 watchEffect()函数
watchEffect()会立即执行一遍回调函数,如果这时函数产生了副作用,Vue 会自动追踪副作用的依赖关系,自动分析出响应源
<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>
<template>
账号:<input type="text" v-model="account">
<hr>
员工薪资:<input type="number" v-model="emp.salary">
</template>
2.2.1 回调的触发时机
默认情况下,用户创建的侦听器回调,都会在 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('-------------------------------------')
console.log('账号:' + account.value)
// 默认情况下,回调触发机制:在 Dom 更新之前
console.log(document.getElementById('titleAccount').innerHTML)
})
// 侦听密码
watchEffect(
() => {
console.log('=====================================')
console.log('密码:' + password.value)
// 默认情况下,回调函数触发机制:在 Dom 更新之前
console.log(document.getElementById('titlePassword').innerHTML)
},
// 更改回调函数触发机制:在 Dom 更新之后
{
flush: 'post' }
)
// 侦听薪资
watchPostEffect(() => {
console.log('=====================================')
console.log('员工薪资:' + emp.salary)
// 回调函数的触发机制:在 Dom 更新之后
console.log(document.getElementById('titleSalary').innerHTML)
})
})
</script>
2.2.2 停止侦听
要手动停止一个侦听器,请调用watchEffect或watchPostEffect()返回的函数
扫描二维码关注公众号,回复: 15267045 查看本文章![]()
<script setup>
import {
ref, watchEffect, watchPostEffect } from 'vue'
// 账号
let account = ref('Abc')
// 密码
let password = ref('123456')
// 调用 watchEffect 返回的函数,可以停止该侦听器
let stopWacthAccount = watchEffect(() => {
console.log('-------------------------------------')
console.log('账号:' + account.value)
})
// 调用 watchPostEffect 返回的函数,可以停止该侦听器
let stopWacthPassword = watchPostEffect(() => {
console.log('=====================================')
console.log('密码:' + password.value)
})
</script>
<template>
账号:<input type="text" v-model="account">
<button @click="stopWacthAccount">停止账号侦听器</button>
<hr>
密码:<input type="text" v-model="password">
<button @click="stopWacthPassword">停止密码侦听器</button>
</template>
2.3 watch和watchEffect的对比
2.3.1 watch
1. watch显式指定依赖数据,依赖数据更新时执行回调函数
2. 具有一定的惰性lazy 第一次页面展示的时候不会执行,只有数据变化的时候才会执行
(设置immediate: true时可以变为非惰性,页面首次加载就会执行)
3. 监视ref定义的响应式数据时可以获取到原值
4. 既要指明监视的属性,也要指明监视的回调
2.3.2 watchEffect
1. watchEffect自动收集依赖数据,依赖数据更新时重新执行自身
2. 立即执行,没有惰性,页面的首次加载就会执行
3. 无法获取到原值,只能得到变化后的值
4. 不用指明监视哪个属性,监视的回调中用到哪个属性就监视哪个属性
总结
以上就是Vue3.0 中watch侦听器的使用方法。希望本篇文章能够帮助到你,不懂得可以评论区或者私信问我,我也会一 一解答。谢谢观看!
我的其他文章:https://blog.csdn.net/m0_60970928?type=blog