学习vue的笔记
1.watch是惰性执行,也就是只有监听的值发生变化才会执行,但watchEffect不同,每次代码加载watchEffect都会执行。
注:(忽略watch第三个参数的配置,如果修改配置项,也可以实现立即执行)。
2.watch需要传递监听的对象,watchEffect不需要。
3.watch只能监听响应式数据:ref定义的属性和reactive定义的对象,如果直接监听reactive定义对象中的属性是不允许的 (会报警告),除非使用函数转换一下,其实就是官网上说的监听一个getter。
4.watchEffect如果监听reactive定义的对象是不起作用的 ,只能监听对象中的属性。
先看一下watchEffect的代码,验证一下
<template>
<div>
请输入firstName:
<input type="text" v-model="firstName">
</div>
<div>
请输入lastName:
<input type="text" v-model="lastName">
</div>
<div>
请输入obj.text:
<input type="text" v-model="obj.text">
</div>
<div>
【obj.text】 {
{obj.text}}
</div>
</template>
以下的方法都用三个 标签做返回。
<script>
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props,content){
let firstName = ref('')
let lastName = ref('')
let obj= reactive({
text:'hello'
})
watchEffect(()=>{
console.log('触发了watchEffect');
console.log(`组合后的名称为:${firstName.value} ${lastName.value}`)
})
return{
obj,
firstName,
lastName
}
}
};
</script>
<script>
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props,content){
let firstName = ref('')
let lastName = ref('')
let obj= reactive({
text:'hello'
})
watchEffect(()=>{
console.log('触发了watchEffect');
// 这里我们不使用firstName.value/lastName.value ,相当于是监控整个ref,对应第四点上面的结论
console.log(`组合后的名称为:${firstName} ${lastName}`)
})
return{
obj,
firstName,
lastName
}
}
};
</script>
<script>
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props,content){
let firstName = ref('')
let lastName = ref('')
let obj= reactive({
text:'hello'
})
watchEffect(()=>{
console.log('触发了watchEffect');
console.log(obj);
})
return{
obj,
firstName,
lastName
}
}
};
</script>
<script>
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props,content){
let firstName = ref('')
let lastName = ref('')
let obj= reactive({
text:'hello'
})
//watchEffect(()=>{
// console.log('触发了watchEffect');
// console.log(obj);
// })
watchEffect(()=>{
console.log('触发了watchEffect');
console.log(obj.text);
})
return{
obj,
firstName,
lastName
}
}
};
</script>
再看一下watch的代码,验证一下
<template>
<div>
请输入firstName:
<input type="text" v-model="firstName">
</div>
<div>
请输入lastName:
<input type="text" v-model="lastName">
</div>
<div>
请输入obj.text:
<input type="text" v-model="obj.text">
</div>
<div>
【obj.text】 {
{obj.text}}
</div>
</template>
以下方法都在这三个标签中回显
<script>
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props,content){
let firstName = ref('')
let lastName = ref('')
let obj= reactive({
text:'hello'
})
// watch是惰性执行, 默认初始化之后不会执行,只有值有变化才会触发,可通过配置参数实现默认执行
watch(obj, (newValue, oldValue) => {
// 回调函数
console.log('触发监控更新了new', newValue);
console.log('触发监控更新了old', oldValue);
})
return{
obj,
firstName,
lastName
}
}
};
</script>
配置immediate参数,立即执行,以及深层次监听
// 配置immediate参数,立即执行,以及深层次监听
watch(obj, (newValue, oldValue) => {
// 回调函数
console.log('触发监控更新了new', newValue);
console.log('触发监控更新了old', oldValue);
}, {
immediate: true,
deep: true
})
监控整个reactive对象,从上面的图可以看到 deep 实际默认是开启的,就算我们设置为false也还是无效。而且旧值获取不到。
要获取旧值则需要监控对象的属性,也就是监听一个getter,看下图
<script>
import { ref, reactive, watch, watchEffect } from "vue";
export default {
name: "HelloWorld",
props: {
msg: String,
},
setup(props, content) {
let firstName = ref("");
let lastName = ref("");
let obj = reactive({
text: "hello",
});
//错误写法,会报警告,这不是监听对象的一个get
// watch(
// obj.text,
// (newValue, oldValue) => {
// // 回调函数
// console.log("触发监控更新了new", newValue);
// console.log("触发监控更新了old", oldValue);
// },
// {
// immediate: true,
// deep: false,
// }
// );
//正确写法
watch(
() => obj.text,
(newValue, oldValue) => {
// 回调函数
console.log("触发监控更新了new", newValue);
console.log("触发监控更新了old", oldValue);
},
{
immediate: true,
deep: true,
}
);
return {
obj,
firstName,
lastName,
};
},
};
</script>
总结:
如果定义了reactive的数据,想去使用watch监听数据改变,则无法正确获取旧值,并且deep属性配置无效,自动强制开启了深层次监听。
如果使用ref初始化一个对象或者数组类型的数据,会被自动转成reactive的实现方式,生成proxy代理对象。也会变得无法正确获取旧值
用任何方式生成的数据,如果接受的变量是一个proxy代理对象,就都会导致watch这个对象时,watch回调里无法正确获取旧值
所以当使用watch监听对象时 ,如果在不需要使用旧值的情况下,可以正常监听对象。
当监听改变函数里面需要用到的旧值时,只能监听 obj.XXX 的方式才行
不理解的参考更多地址: Vue3 中 watch 与 watchEffect 有什么区别?_普通网友的博客-CSDN博客