watch监听
监听reactive定义的数据时
两个小坑:
1.监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
2.监视reactive定义的响应式数据中某个属性时:deep配置有效
let sum1 = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: { salary: 20 },
},
});
const data = reactive({
sum: "",
name2: "",
});
情况一: 监视ref所定义的响应式数据
watch(
sum1,
(newValue, oldalue) => {
console.log("sum1变化了",newValue, oldalue);
},
{ immediate: true }
);
情况二:监听ref所定义的多个响应式数据
watch([sum1, msg], (newValue, oldalue) => {
console.log("sum1或msg变化了", newValue, oldalue);
});
情况三:监听reactive所定义的响应式数据的全部属性
注意:1.此处无法正确的获取oldValue
2.强制开启了深度监视(deep配置无效)
watch(person, (newValue, oldalue) => {
console.log("person变化了", newValue, oldalue);
});
情况四:监听reactive所定义的一个响应式数据中的某个属性,监听的数据要写成函数的形式将其返回
watch(
() => person.name,
(newValue, oldalue) => {
console.log("person的name变化了", newValue, oldalue);
}
);
情况五:监听reactive所定义的一个响应式数据中的某些属性,监听的数据要写成函数的形式将其返回
watch([() => person.name, () => person.age], (newValue, oldalue) => {
console.log("person的name或person的age变化了", newValue, oldalue);
});
特殊情况
此处由于监听的是reactive所定义的对象中的某个属性,所以配置deep配置有效
watch(
() => person.job,
(newValue, oldalue) => {
console.log("person的job变化了", newValue, oldalue);
},
{ deep: true }
);
一般监听对象的话是没有办法正确的获取oldValue
watch监听的三个参数:
第一个:监视的是谁,
第二个:监视的回调,
第三个:监视的配置
监听ref定义的数据时
let sum1 = ref(0);
let msg = ref("你好啊");
let person = ref({
name: "张三",
age: 18,
job: {
j1: { salary: 20 },
},
});
因为sum1里面存的是基本属性类型的值,所以不用.value进行监听
watch(sum1, (newValue, oldValue) => {
console.log("newValue", newValue);
console.log("oldValue", oldValue);
});
watch监听的person.value 即监听的是RefImpl{......} 即RefImpl{......}的value实例对象
即监听的是Proxy
第一种方式
watch(person.value, (newValue, oldValue) => {
console.log("newValue", newValue);
console.log("oldValue", oldValue);
});
第二种方式
watch(
person,
(newValue, oldValue) => {
console.log("newValue", newValue);
console.log("oldValue", oldValue);
},
{ deep: true }
);
watchEffect()函数
watchEffect()会立即执行一遍回调函数,如果这时函数产生了副作用,Vue 会自动追踪副作用的依赖关系,自动分析出响应源
<template>
账号:<input type="text" v-model="account">
<hr>
员工薪资:<input type="number" v-model="emp.salary">
</template>
<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>
回调的触发时机
默认情况下,用户创建的侦听器回调,都会在 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('账号:' + account.value)
// 默认情况下,回调触发机制:在 Dom 更新之前
console.log(document.getElementById('titleAccount').innerHTML)
})
// 侦听密码
watchEffect(
() => {
console.log('密码:' + password.value)
// 默认情况下,回调函数触发机制:在 Dom 更新之前
console.log(document.getElementById('titlePassword').innerHTML)
},
// 更改回调函数触发机制:在 Dom 更新之后
{ flush: 'post' }
)
// 侦听薪资
watchPostEffect(() => {
console.log('员工薪资:' + emp.salary)
// 回调函数的触发机制:在 Dom 更新之后
console.log(document.getElementById('titleSalary').innerHTML)
})
})
</script>
watch和watchEffect的对比
watch
1. watch显式指定依赖数据,依赖数据更新时执行回调函数
2. 具有一定的惰性lazy 第一次页面展示的时候不会执行,只有数据变化的时候才会执行
(设置immediate: true时可以变为非惰性,页面首次加载就会执行)
3. 监视ref定义的响应式数据时可以获取到原值
4. 既要指明监视的属性,也要指明监视的回调
watchEffect
1. watchEffect自动收集依赖数据,依赖数据更新时重新执行自身
2. 立即执行,没有惰性,页面的首次加载就会执行
3. 无法获取到原值,只能得到变化后的值
4. 不用指明监视哪个属性,监视的回调中用到哪个属性就监视哪个属性