当前位置:   article > 正文

vue3 监听器,组合式API的watch用法_vue3 组合式api 监听方法

vue3 组合式api 监听方法

watch函数

在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数

  1. watch(ref,callback(newValue,oldValue),option:{})
  2. ref:被监听的响应式量,可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组
  3. callback:回调函数,当被监听的响应式量变化是触发回调,callback有两个参数,类型和ref一致,值是捕获到的变化后的ref,和变化前的ref
  4. option: 对象提供一些监听函数的监听参数,比如是否开启深层监听

一个最简单的监听示例

  1. <script setup>
  2. import { ref, watch } from 'vue'
  3. const count = ref(0);
  4. watch(count, () => {
  5. console.log(count.value);
  6. })
  7. </script>
  8. <template>
  9. <div>
  10. <span>{{ count }}</span>
  11. </div>
  12. <button @click="count++">click</button>
  13. </template>

当按钮点击时count递增,watch函数会捕获count的变化,并触发回调函数打印出count的值

这里 点击了20下每次变化都触发了一次回调

监听getter

  1. <script setup>
  2. import { ref,reactive, watch } from 'vue'
  3. const count = ref(0);
  4. const obj = reactive({num:0});
  5. watch(count, (num) => {
  6. console.log("count=",num);
  7. })
  8. watch(()=> obj.num , (num) => {
  9. console.log("sum=",num);
  10. })
  11. </script>
  12. <template>
  13. <div>
  14. <span>sum=</span>
  15. <span>{{ count }}+</span>
  16. <span>{{ obj.num }}</span>
  17. </div>
  18. <button @click="count++,obj.num++">click</button>
  19. </template>

这里不能直接监听响应式对象的值(obj.sum ),而是需要用一个返回该属性的 getter 函数要监听的值( ()=> obj.sum ) 

深层监听器

深层侦听需要遍历被侦听对象中的所有嵌套的属性,对于一个对象来说,没有深度监听只有当整个对象改变才会被捕获,

虽然不能直接监听响应式对象的值,但是可以直接监听响应式对象,这会隐式的激活深层监听

  1. <div>
  2. <span>sum=</span>
  3. <span>{{ count }}+</span>
  4. <span>{{ obj.num }}</span>
  5. </div>
  6. <button @click="count++,obj.num++">click</button>

  1. const obj = reactive({num:0});
  2. watch( obj, (newValue,oldValue)=>{
  3. console.log(newValue,oldValue);
  4. })

可以看出来回调的两个对象参数它们式相等的两个值,

当你监听对象内嵌套的对象时,则需要手动开启深层监听,否则只有当整个对象改变时才能被捕获

  1. <div>
  2. <span>sum=</span>
  3. <span>{{ count }}+</span>
  4. <span>{{ obj.num }}</span>
  5. </div>
  6. <button @click="count++,obj.num++,ob.obj.num++">click</button>
  7. <span>嵌套对象的属性{{ ob.obj.num }}</span>
  1. const ob = ref({
  2. obj:{
  3. num:0,
  4. str:"hello"
  5. },
  6. count:0
  7. })
  8. watch(()=>ob.value.obj, (newValue,oldValue)=>{
  9. console.log(newValue,oldValue);
  10. },{
  11. deep:true
  12. })

 可以看到开启深层监听后就可以捕获到变化响应了

立刻回调和一次回调

  1. {
  2. deep:true,
  3. immediate:true,
  4. once:true
  5. }

除了深层回调还有两个参数,immediate,once,布尔值,它们分别表示,立刻执行一次回调(在开始捕获之前)和只回调一次(只捕获一次响应变化)

watchEffect函数

watchEffect会自动监听能访问到的且发生了响应变化的值,并且只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性,这有时候比深层监听遍历所有属性要更好,但是要注意,它仅会在其同步执行期间,才b捕获响应变化。在使用异步回调时,只有在第一个 await 正常工作前访问到的属性才会被捕获。

  1. watchEffect(callback(newValue,oldValue),option:{})
  2. callback:回调函数,当被监听的响应式量变化是触发回调,callback有两个参数,类型和ref一致,值是捕获到的变化后的ref,和变化前的ref
  3. option: 对象提供一些监听函数的监听参数,

watch 和 watchEffect

watch 和 watchEffect 都能响应式地执行能响应的回调(触发页面变化)。它们之间的主要区别是追踪响应式依赖的方式:

watch:需要提供监听目标,监听属性更加精确,仅在监听的目标变化时触发

watchEffect: 不需要提供监听补码,监听时没有那么明确,自动追踪所有能访问到的(参与回调的)响应式属性。

  1. <div :style="`background-color:${color}`">
  2. <span>sum=</span>
  3. <span>{{ count }}+</span>
  4. <span>{{ obj.num }}</span>
  5. </div>
  6. <button @click="count++,obj.num++,ob.obj.num++">click</button>
  7. <button @click="color='green'">change</button>
  8. <span>嵌套对象的属性{{ ob.obj.num }}</span>
  1. watchEffect((newValue,oldValue)=>{
  2. console.log("捕获到了变化",count.value,"\n",newValue,oldValue);
  3. color.value = "red";
  4. })

 回调中有count,当count变化时直接被捕获,改变了背景颜色,同时它还默认响应了一个函数

 回调触发时机

  1. watchEffect(callback,option:{})
  2. option:
  3. flush:post/sync (指明post,则会在响应后回调,指明sync,则会在响应前回调)
  4. // 或者你可以用对应的函数;
  5. watchPostEffect()
  6. watchSyncEffect()
  7. // 它们的效果是一样的

如果想在侦听器回调中能访问被 Vue 更新之后的所属组件的 DOM,你需要指明 flush: 'post' 或者使用 watchPostEffect()

如果想在侦听器回调在 Vue 进行任何更新之前触发:你需要指明 flush: 'sync' 或者使用 watchSyncEffect()

停止监听

在 setup() 或 <script setup> 中,绝大部分的监听器会随着组件销毁而结束。

关键点是,监听器必须用同步语句创建,如果用异步回调创建一个监听器,那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。

手动停止一个侦听器,可以调用 watch 或 watchEffect 返回的函数

  1. const unwatch = watchEffect(() => {})
  2. // ...当该侦听器不再需要时
  3. unwatch()

执行这个返回的函数就可以结束监听,释放内存

代码总结

  1. <script setup>
  2. import { ref,reactive, watch,watchEffect } from 'vue'
  3. const count = ref(0);
  4. const obj = reactive({num:0});
  5. const color = ref("");
  6. const ob = ref({
  7. obj:{
  8. num:0,
  9. str:"hello"
  10. },
  11. count:0
  12. })
  13. watch(count, (num) => {
  14. console.log("count=",num);
  15. })
  16. watch(()=> obj.num , (num) => {
  17. console.log("sum=",num);
  18. })
  19. watch( obj, (newValue,oldValue)=>{
  20. console.log(newValue,oldValue);
  21. })
  22. watch(()=>ob.value.obj, (newValue,oldValue)=>{
  23. console.log(newValue,oldValue);
  24. },{
  25. deep:true,
  26. // immediate:true,
  27. // once:true
  28. })
  29. watchEffect((newValue,oldValue)=>{
  30. console.log("捕获到了变化",count.value,"\n",newValue,oldValue);
  31. color.value = "red";
  32. })
  33. </script>
  34. <template>
  35. <div :style="`background-color:${color}`">
  36. <span>sum=</span>
  37. <span>{{ count }}+</span>
  38. <span>{{ obj.num }}</span>
  39. </div>
  40. <button @click="count++,obj.num++,ob.obj.num++">click</button>
  41. <button @click="color='green'">change</button>
  42. <span>嵌套对象的属性{{ ob.obj.num }}</span>
  43. </template>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/872773
推荐阅读
相关标签
  

闽ICP备14008679号