一键激活Windows和Office:KMS智能脚本完全指南
2026/8/8 16:47:59
watch 是 Vue 3 中用于监听特定数据源变化并执行副作用的 API。它默认是惰性的,只有当监听的源发生变化时才会触发回调函数。这使得 watch 非常适合处理那些需要在特定状态变化时执行的异步操作或复杂逻辑。
export default { data() { return { question: '', answer: 'Questions usually contain a question mark. ;-)', loading: false } }, watch: { // 当 question 变化时,执行此函数 question(newQuestion, oldQuestion) { if (newQuestion.includes('?')) { this.getAnswer() } } }, methods: { async getAnswer() { this.loading = true this.answer = 'Thinking...' try { const res = await fetch('https://yesno.wtf/api') this.answer = (await res.json()).answer } catch (error) { this.answer = 'Error! Could not reach the API. ' + error } finally { this.loading = false } } } }Composition API 方式
<script setup> import { ref, watch } from 'vue' const question = ref('') const answer = ref('Questions usually contain a question mark. ;-)') const loading = ref(false) // 直接监听 ref watch(question, async (newQuestion, oldQuestion) => { if (newQuestion.includes('?')) { loading.value = true answer.value = 'Thinking...' try { const res = await fetch('https://yesno.wtf/api') answer.value = (await res.json()).answer } catch (error) { answer.value = 'Error! Could not reach the API. ' + error } finally { loading.value = false } } }) </script> <template> <p> Ask a yes/no question: <input v-model="question" :disabled="loading" /> </p> <p>{{ answer }}</p> </template>// Options API export default { watch: { 'some.nested.key'(newValue) { // 当嵌套属性变化时触发 } } } // Composition API const obj = reactive({ some: { nested: { key: 0 } } }) watch( () => obj.some.nested.key, (newValue) => { // 当嵌套属性变化时触发 } )// Options API export default { watch: { someObject: { handler(newValue, oldValue) { // 监听对象的所有嵌套属性变化 }, deep: true } } } // Composition API const obj = reactive({ count: 0 }) // 直接监听 reactive 对象会自动创建深度监听 watch(obj, (newValue, oldValue) => { // 当对象的任何嵌套属性变化时触发 })// Options API export default { watch: { question: { handler(newQuestion) { // 组件创建时立即执行一次 }, immediate: true } } } // Composition API watch( question, (newQuestion) => { // 组件创建时立即执行一次 }, { immediate: true } )watchEffect 是 Vue 3 中另一个强大的侦听器 API,它会自动收集回调函数中的依赖,并在依赖发生变化时重新执行回调。与 watch 不同,watchEffect 会在组件创建时立即执行一次,然后在依赖变化时再次执行。
<script setup> import { ref, watchEffect } from 'vue' const todoId = ref(1) const data = ref(null) // 自动收集 todoId.value 作为依赖 watchEffect(async () => { const response = await fetch( `https://jsonplaceholder.typicode.com/todos/${todoId.value}` ) data.value = await response.json() }) </script>watchEffect((onCleanup) => { const controller = new AbortController() fetch(`/api/${id.value}`, { signal: controller.signal }) .then(response => response.json()) .then(data => { // 处理数据 }) // 当依赖变化时,先执行清理函数 onCleanup(() => { controller.abort() }) })// 默认:在组件更新前执行 watchEffect(() => {}) // 在组件更新后执行 watchEffect(() => {}, { flush: 'post' }) // 或使用别名 watchPostEffect(() => {}) // 同步执行,不进行批处理 watchEffect(() => {}, { flush: 'sync' }) // 或使用别名 watchSyncEffect(() => {})| 特性 | watch | watchEffect |
|---|---|---|
| 依赖追踪 | 手动指定监听源 | 自动收集回调中的依赖 |
| 执行时机 | 惰性执行,仅在源变化时触发 | 立即执行,然后在依赖变化时触发 |
| 参数获取 | 可以获取新旧值 | 无法直接获取新旧值 |
| 使用场景 | 监听特定数据源,需要获取新旧值 | 监听多个依赖,不需要关心具体哪个依赖变化 |
使用 watch 的场景:
使用 watchEffect 的场景:
在 Vue 3 中,watch 和 watchEffect 的主要区别是什么?请至少列举 3 点。
答案解析:
如何在 watchEffect 中处理异步操作的副作用清理?请给出代码示例。
答案解析:可以使用 watchEffect 回调函数的第一个参数 onCleanup 来注册清理函数:
watchEffect((onCleanup) => { const controller = new AbortController() fetch(`/api/data`, { signal: controller.signal }) .then(response => response.json()) .then(data => { // 处理数据 }) // 当依赖变化时,先执行此清理函数 onCleanup(() => { controller.abort() // 取消未完成的请求 }) })这个清理函数会在 watchEffect 重新执行前被调用,确保之前的异步操作被正确取消,避免不必要的资源消耗和潜在的错误。
错误表现:
const obj = reactive({ count: 0 }) // 此代码不会生效 watch(obj.count, (newValue) => { console.log('count changed:', newValue) })原因分析:watch 无法直接监听 reactive 对象的属性,需要使用 getter 函数。
解决办法:
watch( () => obj.count, (newValue) => { console.log('count changed:', newValue) } )错误表现:
watchEffect(async () => { const data = await fetchData() // 此处的依赖不会被正确追踪 console.log(user.value.name) })原因分析:watchEffect 只在同步执行阶段收集依赖,异步操作中的依赖不会被追踪。
解决办法:
watchEffect(() => { // 在同步阶段访问依赖 const userId = user.value.id async function fetchData() { const data = await fetch(`/api/user/${userId}`) // 处理数据 } fetchData() })错误表现:在组件卸载后,watch 或 watchEffect 仍然在执行,导致内存泄漏。
原因分析:异步创建的侦听器不会自动与组件绑定,需要手动停止。
解决办法:
// 手动停止侦听器 const unwatch = watchEffect(() => { // 侦听逻辑 }) // 在组件卸载时停止 onUnmounted(() => { unwatch() })