# 1.watchEffect 自动收集依赖
App 为根组件 下面 Home 例子都被此组件引用
// App.vue | |
<template> | |
<div> | |
<home></home> | |
</div> | |
</template> | |
<script> | |
import Home from "./Home.vue"; | |
export default { | |
components: { | |
Home, | |
}, | |
}; | |
</script> | |
<style scoped> | |
</style> |
// Home.vue | |
<template> | |
<div> | |
<h2>{{ name }}-{{ age }}</h2> | |
<button @click="changeName">修改name</button> | |
<button @click="changeAge">修改age</button> | |
</div> | |
</template> | |
<script> | |
import { ref, watchEffect } from "vue"; | |
export default { | |
setup() { | |
//watchEffect: 自动收集响应式的依赖 | |
const name = ref("Neko"); | |
const age = ref(16); | |
const changeName = () => (name.value = "Nico"); | |
const changeAge = () => age.value++; | |
//watchEffect 与 watch 不同,它会默认立即执行一次 类似 watch 中的 immediate: true | |
watchEffect(() => { | |
// 因为 watchEffect 会收集依赖 | |
console.log("name:", name.value, "age:", age.value); | |
}); | |
return { | |
name, | |
age, | |
changeName, | |
changeAge, | |
}; | |
}, | |
}; | |
</script> | |
<style scoped> | |
</style> |
参考结果:
# 2.watchEffect 的返回值 (function)
- 使用 watchEffect 的返回值做一个当 age > 20 就停止监听 的小案例
// Home | |
<template> | |
<div> | |
<h2>{{ name }}-{{ age }}</h2> | |
<button @click="changeName">修改name</button> | |
<button @click="changeAge">修改age</button> | |
</div> | |
</template> | |
<script> | |
import { ref, watchEffect } from "vue"; | |
export default { | |
setup() { | |
//watchEffect: 自动收集响应式的依赖 | |
const name = ref("Neko"); | |
const age = ref(16); | |
const changeName = () => (name.value = "Nico"); | |
const changeAge = () => { | |
age.value++; | |
if (age.value > 20) { | |
stop(); // 条件满足停止监听 | |
} | |
}; | |
//watchEffect 与 watch 不同,它会默认立即执行一次 类似 watch 中的 immediate: true | |
const stop = watchEffect(() => { | |
// 因为 watchEffect 会收集依赖 | |
console.log("name:", name.value, "age:", age.value); | |
}); | |
console.log("watchEffect的返回值:", stop); // 看看 watchEffect 的返回值 | |
return { | |
name, | |
age, | |
changeName, | |
changeAge, | |
}; | |
}, | |
}; | |
</script> | |
<style scoped> | |
</style> |
参考结果:
# 3.watchEffect 清除副作用
// Home | |
<template> | |
<div> | |
<h2>{{ name }}-{{ age }}</h2> | |
<button @click="changeName">修改name</button> | |
<button @click="changeAge">修改age</button> | |
</div> | |
</template> | |
<script> | |
import { ref, watchEffect } from "vue"; | |
export default { | |
setup() { | |
//watchEffect: 自动收集响应式的依赖 | |
const name = ref("Neko"); | |
const age = ref(16); | |
const changeName = () => (name.value = "Nico"); | |
const changeAge = () => age.value++; | |
//watchEffect 与 watch 不同,它会默认立即执行一次 类似 watch 中的 immediate: true | |
const stop = watchEffect((onInvalidate) => { | |
// 模拟网络请求 | |
const timer = setTimeout(() => { | |
console.log("网络请求成功~"); | |
}, 2000); | |
// 在这个函数中清除额外的副作用 | |
onInvalidate(() => { | |
clearTimeout(timer); // 有点像 debounce, 一直点击会不断取消掉网络请求 timer | |
console.log("onInvalidate"); | |
}); | |
console.log("name:", name.value, "age:", age.value); | |
}); | |
return { | |
name, | |
age, | |
changeName, | |
changeAge, | |
}; | |
}, | |
}; | |
</script> | |
<style scoped> | |
</style> |
参考结果:
# 4. 总结
watchEffect
默认会执行一次watchEffect
的返回值是一个函数,因此可以在条件满足的情况下调用函数来停止监听watchEffect
的参数:effect
是函数effect
自己也有参数:onInvalidate
,也是一个函数,用于清除effect
产生的副作用。watchEffect
可以用来发送网络请求,用onInvalidate
来清除,效果类似debounce
watchEffect
是没有 oldValue