1.什么是watch监听器
在 Vue 3 中,watch 主要用于组合式 API 中配合 ref 或 reactive 创建的响应式数据。watch 可以帮助我们在数据发生变化时执行副作用操作,比如发起 API 请求、修改其他状态或执行某些计算等。
2.基本用法
watch 主要接受两个参数:
- 第一个参数:要监听的响应式数据。
- 第二个参数:当第一个参数变化时执行的回调函数。
举个例子:
<script setup>
import { ref, watch } from 'vue'
// 定义响应式数据
const message = ref('')
// 使用 watch 监听 message 的变化
watch(message, (newValue, oldValue) => {
console.log(`Message changed from "${oldValue}" to "${newValue}"`)
})
</script>
<template>
<div>
<input v-model="message" placeholder="Enter something"/>
<p>{{ message }}</p>
</div>
</template>
在上面的例子中:
message是一个响应式的数据。- 回调函数有两个参数:
newValue和oldValue,分别表示数据的新值和旧值。
如果回调函数的参数只写一个,代表新值,比如:
3.使用场景
这个是我最关心
vue3官方文档这样写道:
比如,在个人博客项目中,我通过watch来监听主页面的主题切换情况,跟着切换markdown编辑器的主题。
因为这个markdown编辑器默认是可以切换明暗模式的:
问题来了,为什么要监听,直接把
adminStore.theme给编辑器主题editorTheme不好吗?
直接将 adminStore.theme 赋值给 editorTheme 是不够灵活的,因为你无法控制 editorTheme 的初始值,且它会一直同步更新。
通过 watch,你可以控制 editorTheme 的初始值,以及在 adminStore.theme 变化时如何更新 editorTheme。同时,可以在变化时为 editorTheme 提供一个合理的默认值,比如 'light',以避免 adminStore.theme 为 null 或 undefined 时出现问题。
但是,注意:这个代码中的第一个参数是() => adminStore.theme,为什么不直接写adminStore.theme呢?
adminStore本身是一个响应式对象,用pinia定义的:
export const useAdminStore = defineStore(
'blog-front-ultimate',
() => {
const token = ref('')
const admin = ref({})
const theme = ref('')
const setToken = (newToken) => {
token.value = newToken
}
const removeToken = () => {
token.value = ''
}
const getAdmin = async () => {
const result = await adminGetInfoService()
admin.value = result.data
}
//清除用户信息
const setAdmin = (obj) => {
admin.value = obj
}
const setTheme = (newTheme) => {
theme.value = newTheme
}
const getTheme = () => {
return theme.value
}
return {
token,
setToken,
removeToken,
admin,
getAdmin,
setAdmin,
theme,
setTheme,
getTheme,
}
},
{
persist: true,
},
)
但是,Vue 的 watch 不会自动深度监听对象的某个属性值(如 adminStore.theme),因为它的属性 theme 并不是直接的响应式对象,而是嵌套在一个响应式对象中。
用函数访问属性:
watch(() => adminStore.theme, (newTheme) => {
console.log(`Theme changed to ${newTheme}`);
});
通过 () => adminStore.theme,我们明确告诉 watch,需要监听的是 adminStore.theme 的值。
但是,我还是不明白,为什么用箭头函数,vue就可以监听到adminStore.theme😁,算了,越挖越深了,就这样吧。