Vue3 – watch 组合式API
简介
watch 是 Vue 提供的一个比较有用的功能,它可以监视数据发生变化时的自定义操作。在Vue3 中提供的 watch 功能与 Vue2 基本一样的,但使用上有一些不同。
watch
Vue2 中的 watch
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 需要引入才能使用,并且,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
}
}
}
watch 监视 reactive 响应式数据
watch 监听普通 reactive 响应式数据
对于普通的 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
}
}
}
watch 监听 reactive 响应式数据中的普通数据成员
当我只希望监听 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
}
}
}
watch 监听 reactive 响应式数据中的对象成员
如果 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
}
}
}
watch 监听 reactive 响应式数据中的多个普通数据
同样需要使用 ()=>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
watchEffect 是Vue3 新推出的一种watch功能,它需要接收一个带有函数“onCleanup”的回调函数,在这个回调函数中,所涉及到的变量,都会被智能监听,当这些变量数据发生变化时,watchEffect 的回调函数就会被执行,所传入的“onCleanup”函数执行时,可用于副作用(指的是该功能以外的其它操作,如在监听中反间理异步请求)的清理。
watchEffect 的返回值是该清理副作用的函数,通过调用返回值,使watchEffect 失效。
const stop = watchEffect(() => {})
// 当不再需要此侦听器时:
stop()
onCleanup 的作用,是为了考虑到一些操作还没完成时,但数据再一次发生变化而触发watchEffect 时,对前一次未完成的操作进行停止或清理。
举个例子:
当 watchEffect 中监听 person.name 值,当person.name值发生改变时,触发watchEffect 并把person.name的值异步请求服务器。
但是,当异步请求还没完成之际,person.name 值再次发生改变,watchEffect 再次被触发,这就有可能上一次请求还完成,又要发一次请求,针对这样的问题,我们应该先清理上一次未完成的请求操作,再去处理新的请求,则可以调用 onCleanup() 方法
flush 是指 watchEffect 函数触发的时机,有三种情况,默认是 pre
pre 指的是,当监听数据发生改变时,在页面渲染前,就调用watchEffect 函数
post 指的是,当监听数据发生改变时,在页面演染完成后,再调用watchEffect 函数
sync 指的是,watchEffect 监听多个数据时,应保持同步触发,效率较低不建议使用
代码如下:
// 引用 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
*/
const stop = watchEffect((onCleanup)=>{
const x1 = person.job.j1.salary;
(对 person.job.j1.salary 进行一些操作)
const x2 = person.name;
(对 person.name 进行一些操作)
onCleanup(()=>{
如果有异步请求,则需要在这里清理请求
})
},{
flush:'pre'|'post'|'sync'
})
return {
person
}
}
}
共有 0 条评论