watch 是 Vue 提供的一个比较有用的功能,它可以监视数据发生变化时的自定义操作。在Vue3 中提供的 watch 功能与 Vue2 基本一样的,但使用上有一些不同。
Vue2 中的watch 使用的是对象配置项,如下代码:
export default {
name: 'App',
data() {
return {
sum: 0,
sum2: 0
}
},
watch: {
// 使用简易的声明watch方式
sum(newValue, oldValue) {
console.log("sum数据发生变化", newValue, oldValue)
},
// 使用对象配置的声明watch方式
sum2:{
// 初始化后即开启一次监视
immediate:true,
// 针对多种嵌套的对象进行深度监视
deep:true,
handler(newValue, oldValue){
console.log("sum数据发生变化", newValue, oldValue)
}
}
}
}
Vue3 中的 watch 需要引入才能使用,并且,Vue3的 watch 是一个API方法,因此可以多次调用,并且,watch可以同时监视多个变量的数据变化,如下参考代码:
// 引用 watch 监视属性的引用
import {watch} from "vue"
export default {
name: 'App',
setup() {
let sum = ref(0);
let sum2 = ref(0);
/**
* Vue3 中的定义 watch 用法
* 参数一:要监视的变量
* 参数二:变量发生改变时的触发的方法体(Vue2中的 handler())
* 参数三:对于变量监视的额处配置属性(如immediate和 deep参数)
*/
watch(sum, (newValue, oldValue) => {
console.log("sum数据发生改变", newValue, oldValue)
}, {
immediate: true,
deep: true
})
/**
* Vue3 中可以定义无数个 watch 方法来监视每一个变量
* 也可以使用一个 watch 方法来一次监视多个变量
* 参数一:使用数组包装要监视的多个变量
* 参数二:变量发生改变时的触发的方法体(Vue2中的 handler()),接收到的 value 也将是提供数组
* 参数三:对于变量监视的额处配置属性(如immediate和 deep参数)
*/
watch([sum, sum2], (newValue, oldValue, onCleanup) => {
// 这里的 newValue 和 oldValue 都将是数组包装的数据
console.log("sum或sum2数据发生改变", newValue, oldValue)
}, {immediate: true, deep: true});
return {
sum, sum2
}
}
}
对于普通的 reactive 响应式数据时,将强制开启深度监视。
// 引用 watch 监视属性的引用
import {reactive, watch} from "vue"
export default {
name: 'App',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
/**
* watch 普通监听 reactive 响应式数据
* 情况一:当普通监听 reactive 响应式数据时,
* 会强制开启 deep:true 深度监听,即使关闭了,也会监听深度对象成员
*/
watch(person, (newValue, oldValue, onCleanup) => {
console.log("person数据发生变化", newValue, oldValue);
}, {deep:false}) // 这里即使 deep:false ,但依然产生深度监视
return {
person
}
}
}
当我只希望监听 reactive 响应式数据里的基础数据类型时的代码如下
// 引用 watch 监视属性的引用
import {reactive, watch} from "vue"
export default {
name: 'App',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
/**
* watch 监听 reactive 响应式数据中的普通类型数据
* 情况二:当监听 reactive 响应式数据中的普通类型数据时
* 不可以直接使用监听,需要使用方法返回值的方式获得
* 使用这种方式的监听,newValue, oldValue 是有效的
*/
watch(() => person.name, (newValue, oldValue, onCleanup) => {
console.log("person.name数据发生变化", newValue, oldValue)
})
return {
person
}
}
}
如果 reactive 响应式数据里嵌套了对象数据时,若我只希望监听该对象数据时的代码如下:
// 引用 watch 监视属性的引用
import {reactive, watch} from "vue"
export default {
name: 'App',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
/**
* watch 监听 reactive 响应式数据中的对象数据
* 情况三:当监听 reactive 响应式数据中的对象数据时
* deep 将会生效,不加上deep:true 时,将监听不到数据变化
* 使用这种方式的监听,newValue, oldValue 是有效的
*/
watch(() => person.job, (newValue, oldValue, onCleanup) => {
console.log("person.job数据发生变化", newValue, oldValue)
}, {deep: true})
return {
person
}
}
}
同样需要使用 ()=>xx 方式返回数据,否则会出现无法监听的问题。
// 引用 watch 监视属性的引用
import {reactive, watch} from "vue"
export default {
name: 'App',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
/**
* watch 监听 reactive 响应式数据中的多个普通数据
* 情况四:当监听 reactive 响应式数据中的多个普通数据时
*
* 使用这种方式的监听,newValue, oldValue 是有效的
*/
watch([() => person.name, () => person.age], (newValue, oldValue, onCleanup) => {
console.log("person中的普通数据发生变化", newValue, oldValue)
})
return {
person
}
}
}
watchEffect 是Vue3 新推出的一种watch功能,它需要接收一个无参的回调函数,它不需要定义监听对象,回调函数中使用到了什么对象数据,它就会智能的监听什么对象,当回调函数中使用到的对象数据发生变化时,它就会发生监听触发。
代码如下:
// 引用 watchEffect 监视属性的引用
import {reactive, watchEffect} from "vue"
export default {
name: 'App',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
/**
* watchEffect 会对其回调函数中被使用的数据进行智能监听
* 本例中,回调函数中使用了 person.job.j1.salary 和 person.name 数据
* 则当这两个数据发生变化时,watchEffect会被触发
* 而没有在回调函数中使用的数据(如 person.age)被改变时, 不会触发 watchEffect
*/
watchEffect(()=>{
const x1 = person.job.j1.salary;
const x2 = person.name;
})
return {
person
}
}
}