vue3.0 watch
和watchEffect区别:(1)不会立即执行,当侦听的源变更时才会执行(2)可以监听多个数据源相同:watch和watchEffect在停止侦听,清除副作用(相应地onInvalidate会作为回调的第三个参数传入),副作用刷新时机和侦听器调试等方面行为一致.使用import { watch } from 'vue'setup(){(1)监听单个数据源方式一:通过函数返回值watch(()=&
·
与选项式API this.$watch(以及相应的watch选项)完全等效
和watchEffect区别:
(1)不会立即执行,当侦听的源变更时才会执行
(2)可以监听多个数据源
(3)更具体地说明什么状态应该触发侦听器重新运行
(4)访问侦听状态变化前后的值
相同:
watch和watchEffect在停止侦听,清除副作用(相应地onInvalidate会作为回调的第三个参数传入),副作用刷新时机和侦听器调试等方面行为一致.
使用
import { watch } from 'vue'
setup(){
(1)监听单个ref
方式一:
通过函数返回值
watch(()=>{
return x.value 一般用于监听对象中的单个属性,因为watch第一个参数类型得是对象
},(state,preState)=>{
...
})
方式二:
通过直接放置ref
watch(x,(state,preState)=>{
...
})
(1.1)监听reactive对象
(1)数组:
const array = reactive([1, 2, 3, 4])
watch(
() => [...array],
(numbers, prevNumbers) => {
console.log(numbers, prevNumbers)
}
)
(2)对象
const obj= reactive({...})
watch(
obj, 默认监听对象内所有属性的变更
(state, prevState) => {
console.log('not deep', state.attributes.name, prevState.attributes.name)
}
)
watch(
() => obj, 只有当返回不同的对象时,才会触发监听
(state, prevState) => {
console.log('not deep', state.attributes.name, prevState.attributes.name)
}
)
(3)不能直接监听对象的普通属性(如number、string等),需要一个getter函数
const obj = reactive({ count: 0 })
这不起作用,因为你是向 watch() 传入了一个 number
watch(obj.count, (count) => {
console.log(`count is: ${count}`)
})
提供一个 getter 函数
watch(
() => obj.count,
(count) => {
console.log(`count is: ${count}`)
}
)
(1.5)具有和vue2中的watch等效的配置
watch(x,fn,{
immediate:true, 第一次就会执行回调
deep:true 深度监视
...
})
(2)监听多个数据源
watch([x,x1,...],([x,x1],[prex,prex1])=>{
...
})
vue3.2:
watch([x,x1,...], (newValues, prevValues) => {
newValues 包含更新后的值[x,x1,..]
prevValues 包含更新前的值[x,x1,..]
})
(3)清除副作用、监听侦听器、要同步或在组件更新之前配置
watch(x,(state,preState,onInvalidate)=>{
...
onInvalidate(){
执行时机:
在副作用即将重新执行时
如果在setup()或生命周期钩子函数中使用了watchEffect, 则在卸载组件时
}
}),{
flush: 'sync', 'pre'组件更新前运行
onTrigger(e) {
依赖项变更导致副作用被触发时
e.taget包含了值
},
onTrack(e){
当一个 reactive对象属性或一个 ref 作为依赖被追踪时触发
e.taget包含了值
}
}
}
(4)手动停止侦听:
const xx=watch(...)
xx.stop();
2、卸载watch时机
异步回调创建一个侦听器,那么它不会绑定到当前组件上,必须手动停止它,以防内存泄漏,同步则不用
需要手动卸载:
setTimeout(() => {
watch...
}, 100)
代码示例:
<template>
<div>
<img src="./logo.png">
<h1>Hello Vue 3!</h1>
{{name}}{{obj.sex}}
<button @click="inc">Clicked {{ count }} times.</button>
</div>
</template>
<script>
import { ref,reactive,computed,readonly,watchEffect,watch } from 'vue'
export default {
setup() {
let count = ref(0)
let count2=ref(2);
let name = ref('jeff')
const obj=reactive({sex:'male'})
const robj=readonly(obj);
let timer;
let r=readonly('aa') //不具有只读的能力
watch(()=>{
return count.value
},(count,prevcount,onInvalidate)=>{
console.log(count);
console.log(prevcount);
onInvalidate(()=>{
console.log('清除');
})
},{
onTrigger(e) {
console.log(e);
}
})
// watch(count,(count,prevcount)=>{
// console.log(count);
// console.log(prevcount);
// })
// watchEffect((onInvalidate)=>{
// console.log(count.value);
// onInvalidate(()=>{
// console.log('清除');
// clearInterval(timer);
// })
// }, {
// onTrigger(e) {
// console.log(e);
// },
// onTrack(e)
// {
// console.log('triger');
// console.log(e)
// }
// })
const inc = () => {
count.value++;
// timer=setInterval(()=>{
// count.value++;
// },1000)
}
return {
count,
inc,
name, //在setup返回对象中自动解套
obj
}
}
}
</script>
<style scoped>
img {
width: 200px;
}
h1 {
font-family: Arial, Helvetica, sans-serif;
}
</style>
更多推荐
已为社区贡献20条内容
所有评论(0)