watchEffect
传入一个副作用函数并执行,追踪函数内依赖的变量,当依赖的变量发生变化时再次执行副作用函数函数。
当副作用函数依赖一个变量
<template>
<div>
</div>
</template>
<script lang="ts" setup>
import {ref, watchEffect} from "vue";
let count = ref(0)
watchEffect(() => {
console.log('count:', count.value);
})
setInterval(() => {
count.value++
}, 1000)
</script>
控制台日志如下:
当副作用函数依赖多个变量
每个变量变化时都会触发副作用函数
<template>
<div>
</div>
</template>
<script lang="ts" setup>
import {ref, watchEffect} from "vue";
let count = ref(0)
let count1 = ref(0)
watchEffect(() => {
console.log('count:', count.value);
console.log('count1:', count1.value);
})
setInterval(() => {
count.value++
}, 1000)
setInterval(() => {
count1.value++
}, 500)
</script>
停止侦听
watchEffect
会返回一个停止侦听的函数,执行次函数就可以停止侦听依赖变量的变化
<template>
<div>
</div>
</template>
<script lang="ts" setup>
import {ref, watchEffect} from "vue";
let count = ref(0)
const stop = watchEffect(() => {
console.log('count:', count.value);
})
setInterval(() => {
count.value++
}, 1000)
setTimeout(() => {
stop()
}, 5000)
</script>
清除副作用
副作用函数传入一个函数变量onInvalidate
用于设置一个回调函数B,从第二次执行副作用函数以及组件卸载时会先执行回调函数B。
例如:依赖变量发生变化时请求接口数据,当第一次接口数据正在请求时,依赖的变量再次发生变化,此时可在回调函数B设置取消上一次的接口请求的操作
import {ref, watchEffect} from "vue";
import axios from "axios";
let count = ref(0)
watchEffect(async (onInvalidate) => { // 会马上执行此副作用函数,并在count.value发送变化时再次执行
let a = count.value
let source = axios.CancelToken.source() // 用于取消接口请求的token
axios.get('', { // 使用当前页面作为测试接口
cancelToken: source.token
}).then(res => {
console.log('success',a, res);// 请求成功
}).catch(reason => {
console.log('fail', a, reason);// 请求失败
})
onInvalidate(() => { // 当副作用函数多次执行或者组件被卸载时执行此回调函数
console.log('onInvalidate')
source.cancel() // 取消接口请求
})
})
count.value++ // 触发第二次执行副作用函数
setTimeout(() => {
count.value++ // 触发第三次执行副作用函数
}, 2000)
控制台输出日志
副作用函数的执行时机
通过watchEffect
的第二个参数配置副作用函数的执行时机
watchEffect(() => {}, {
flush: 'post'|'pre'|'sync'
})
post
:组件渲染完成后执行副作用函数pre
: 组件渲染之前执行副作用函数sync
:立即执行副作用函数
<template>
<div id="ss">
{{count}}
</div>
</template>
<script lang="ts" setup>
import {ref, watchEffect} from "vue";
let count = ref(0)
watchEffect(() => {
console.log('sync', count.value)
let s = document.getElementById('ss')
console.log(s&&s.innerHTML)
}, {
flush: 'sync'
})
watchEffect(() => {
console.log('pre', count.value)
let s = document.getElementById('ss')
console.log(s&&s.innerHTML)
}, {
flush: 'pre'
})
watchEffect(() => {
console.log('post', count.value)
let s = document.getElementById('ss')
console.log(s&&s.innerHTML)
}, {
flush: 'post'
})
setTimeout(() => {
console.log('update count--------------------------')
count.value++
console.log('update count1++++++++++++++++++++++++')
}, 2000)
</script>
<style scoped lang="scss">
</style>