您现在的位置是:首页 > 编程语言学习 > 前端编程语言 > 文章正文 前端编程语言

讲解vue3中的watch监听的作用及使用方法

2022-11-18 10:22:40 前端编程语言

简介我们先说下watch监听的作用:1,计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些副作用;2,例如更...

我们先说下watch监听的作用:

  • 1,计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”;
  • 2,例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数从而来进行一些其它的操作;
  • 3,可以在页面使用多次;

1,可以监听什么数据:

watch监听 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组;

2,使用监听:

  1. <script setup> 
  2. import { reactive, ref, watch, onMounted } from "vue"
  3. // 定义响应式数据 
  4. const message = ref(""); 
  5. const a = ref(1); 
  6. const b = ref(2); 
  7. const messageList = ref([ 
  8.   { name: "Eula", age: "18", isActive: false }, 
  9.   { name: "Umbra", age: "17", isActive: false }, 
  10.   { name: "Kaya", age: "19", isActive: false }, 
  11.   { name: "Diluk", age: "19", isActive: false }, 
  12. ]); 
  13. const obj = reactive({ count: 0 }); 
  14.  
  15. // 定义一个简单的seeter函数 
  16. function count() { 
  17.   return a.value + b.value; 
  18.  
  19. // 1,监听一个响应式字符串 
  20. watch(message, (newX) => { 
  21. // 如果等于123 来修改messageList的值 看messageList的变化会不会被监听:可以监听到 数组需要添加深度监听 
  22.   if (newX == "123") { 
  23.     messageList.value.push({ name: "222" }); 
  24.     console.log("messageList.value", messageList.value); 
  25.   } 
  26. }); 
  27.  
  28. //2,监听一个响应式数组  要使用深度监听 deep:true 
  29. watch( 
  30.   messageList, 
  31.   (newX) => { 
  32.     console.log(`拿到改变后的数组:`, messageList.value); 
  33.  
  34.     // 如果等于3 在改变a的值看下面的count函数会不会监听到  监听到了 
  35.     if (count() == 3) { 
  36.       a.value = 3; 
  37.     } 
  38.   }, 
  39.   { deep: true } 
  40. ); 
  41.  
  42. // 3,监听一个函数 
  43. watch(count, (newX) => { 
  44.   console.log("新的函数值:", newX); // 3+2 = 5 监听到了 函数值的变化 
  45. }); 
  46.  
  47. //4,多个来源组成的数组  按照顺序进行监听的 
  48. watch([message, messageList, count], ([newX, newY, newZ]) => { 
  49.   console.log("监听的数组第一项newX:", newX); 
  50.   console.log("监听的数组第二项newY:", newY); 
  51.   console.log("监听的数组第三项newX:", newZ); 
  52. }); 
  53.  
  54. onMounted(() => { 
  55.   console.log("Mounted"); 
  56. }); 
  57. </script> 
  58.  
  59. <template> 
  60.   <div class="watch"
  61.     <h3>watch监听演示</h3> 
  62.     <p>Message is: {{ message }}</p> 
  63.     <input v-model="message" placeholder="请输入123触发其它监听" /> 
  64.   </div> 
  65. </template> 
  66.  
  67. <style scoped></style> 

3,监听器里面可以进行异步操作:

触发监听后可以立即执行异步的请求操作;这解决了计算属性不能操作异步的弊端;因为计算属性(computed)是通过return返回值传递参数 异步操作的时候return是没有意义的;

  1. <script setup> 
  2. import { ref, watch } from 'vue' 
  3.  
  4. const question = ref(''
  5. const answer = ref('Questions usually contain a question mark. ;-)'
  6.  
  7. // 可以直接侦听一个 ref 
  8. watch(question, async (newQuestion, oldQuestion) => { 
  9.   if (newQuestion.indexOf('?') > -1) { 
  10.     answer.value = 'Thinking...' 
  11.     try { 
  12.       const res = await fetch('https://yesno.wtf/api'
  13.       answer.value = (await res.json()).answer 
  14.     } catch (error) { 
  15.       answer.value = 'Error! Could not reach the API. ' + error 
  16.     } 
  17.   } 
  18. }) 
  19. </script> 
  20.  
  21. <template> 
  22.   <p> 
  23.     Ask a yes/no question: 
  24.     <input v-model="question" /> 
  25.   </p> 
  26.   <p>{{ answer }}</p> 
  27. </template> 

4,不能直接监听响应式对象的属性值

  1. const obj = reactive({ count: 0 }) 
  2. // 错误,因为 watch() 得到的参数是一个 number 
  3. watch(obj.count, (count) => { 
  4.   console.log(`count is: ${count}`) 
  5. }) 

解决方法:需要使用一个函数返回这个属性值

  1. // 提供一个 getter 函数 
  2. watch( 
  3.   () => obj.count, 
  4.   (count) => { 
  5.     console.log(`count is: ${count}`) 
  6.   } 

5,watchEffect与 watch的区别

  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。 watch会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
  • 默认情况下,watch 是惰性的,因此仅当依赖项更改时才会触发。watchEffect 在创建组件后立即运行,然后跟踪依赖关系。
  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。

6,回调的触发时机

当你更改了响应式状态,它可能会同时触发 Vue 组件更新和侦听器回调。 默认情况下,用户创建的侦听器回调,都会在 Vue组件更新之前被调用。这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。

如果想在侦听器回调中能访问被 Vue 更新之后的DOM,你需要指明 flush: ‘post’ 选项:

  1. watch(source, callback, { 
  2.   flush: 'post' 
  3. }) 
  4. watchEffect(callback, { 
  5.   flush: 'post' 
  6. }) 

后置刷新的 watchEffect() 有个更方便的别名 watchPostEffect():

  1. import { watchPostEffect } from 'vue' 
  2. watchPostEffect(() => { 
  3.   /* 在 Vue 更新后执行 */ 
  4. }) 

7,停止侦听器 watch 或 watchEffect都会返回一个函数;我们可以通过调用这个函数来手动结束这个监听;

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

 

相关文章

站点信息