- Overview
-
立即运行一个回调函数|副作用,同时自动感知代码依赖|追踪其中的数据源,并在其变化时重新执行回调函数
关注的是数据的状态变化,并不关注数据变化前后的值
需引入包 watchEffect
import { watchEffect } from 'vue'
function watchEffect(
effect: (onCleanup: OnCleanup) => void,
options?: WatchEffectOptions
): StopHandle
effect:回调函数,也叫副作用函数 side effect,即某种操作,如对外部可变数据或变量的修改,外部接口的调用等
onCleanup:回调函数的可选参数,是一个函数,用来注册清理回调;清理回调会在该副作用下一次执行前被调用
options:可选的选项,可以用来调整副作用的刷新时机或调试副作用的依赖
StopHandle:自动侦听器函数返回一个停止器函数,详见后续内容
-
watchEffect:会立即执行传入的函数,并自动追踪其中的所有响应式依赖。当这些依赖发生变化时,它会重新运行该函数
watch:需要显式指定要监听的响应式数据源(如 ref 或 reactive 对象),并且只在这些数据源变化时触发回调
watchEffect 也称自动侦听器,等同于使用了立即配置项 immediate;执行1-N次
watch 仅在侦听的数据源确实改变时才会触发回调;执行0-N次
watchEffect 更有效,只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性;但是不能获取旧值
watch 控制更为精细;旧值、新值、deep、immediate
- 停止侦听
-
在大多数情况下,你无需关心怎么停止一个侦听器
要手动停止一个侦听器,请调用 watchEffect 返回的函数
const stopWatchEffect = watchEffect(num, (newv, oldv) => {})
stopWatchEffect()
- [] 侦听多个数据,如 name 和 age
-
let num = ref(1)
let msg = ref('')
1. 使用侦听 watch - 分别单独侦听
watch(num, (newVal, oldVal) => {
sum.value = newVal * price
}, { immediate: true })
watch(msg, (newVal, oldVal) => {
console.log('msg', newVal)
})
2. 使用自动侦听 watchEffect
watchEffect(() => {
sum.value = num.value * price
console.log('msg', msg.value)
})
- [] 换肤 - 更新自定义属性实现
-
1. 准备2套变量
:root {
--bg-color: #fff;
--txt-color: #333;
}
html[data-theme='dark'] {
--bg-color: #333;
--txt-color: #fff;
}
2. 准备元素并添加事件,改变主题的值
<button @click="setMode">darkMode</button>
3. 准备数据并自动监听主题
import { ref, watchEffect } from 'vue'
let darkMode = ref('light')
const setMode = () => {
darkMode.value = darkMode.value === 'light' ? 'dark' : 'light'
}
watchEffect(() => {
document.documentElement.setAttribute('data-theme', darkMode.value)
// or
document.documentElement.dataset.theme = darkMode.value
})
- [] 使用自动侦听改写 积分榜
-
1. 采用回调函数 callback 方式
watchEffect(
() => {
fetch(`https://glpla.github.io/utils/data/rank/${word.value}`)
.then(res => res.json())
.then(data => {
console.log(data);
})
}
)
2. 采用异步等待 async-await 方式
watchEffect(async () => {
const res = await fetch(`https://glpla.github.io/utils/data/rank/${word.value}`)
const data = await res.json()
console.log('data', data)
})
3. 改进
. 加入加载指示器/进度条 - 条件渲染
<div class="loading" v-show="isLoading">loading</div>
const isLoading = ref(false)
watchEffect(async () => {
isLoading.value = true
const res = await fetch(`https://glpla.github.io/utils/data/rank/${word.value}`)
const data = await res.json()
console.log('data', data)
isLoading.value = false
})
. 加入异常处理 try-catch;参考下例
- [] 下拉菜单
-
使用下拉列表的双向绑定触发自动加载数据
应用1:门店/地址切换
应用2:加载不同类别的商品
<select v-model="selectedCategory">
<option value="electronics">电子产品</option>
<option value="clothing">服装</option>
<option value="books">书籍</option>
</select>
watchEffect(async () => {
try {
const response = await axios.get(`/api/items?category=${selectedCategory.value}`)
items.value = response.data
} catch (error) {
console.error(error)
}
})
- [] 瑞幸咖啡首页标签页 - 随享瑞幸、颜值水杯 -
的变化触发数据加载;后期可以使用使用 动态组件 实现
- [] 分析下面代码的功能
-
watchEffect((onCleanup) => {
str.value = msg.value.split('').reverse().join('');
onCleanup(()=>{
console.log('clean done');
})
})