vue3保證你看懂watch和watchEffect的詳細詳細使用

南風晚來晚相識發表於2022-01-10

watch 監聽 reative 建立的值

const state = reactive({ nickname: "xiaofan", age: 20 });

setTimeout(() => {
  state.age++;
}, 800);

// 修改age值時會觸發 watch的回撥
watch(
  () => state.age,   //監聽state中的age
  (newValue, oldValue) => {
	console.log("新值:", newValue, "老值:", oldValue);
  }
);

watch 監聽 ref 建立的值

const year = ref(100);

setTimeout(() => {
  year.value++;
}, 1000);

watch(() => state.value, (newValue, oldValue) => {
  console.log("新值:", newValue, "老值:", oldValue);
});

watch 監聽多個值

const state = ref(100)
let  person=reactive({
  name:'zs'
})

setTimeout(() => {
  state.value++;
  person.name='李四'
}, 800);

watch(()=>[state.value,   person.name ],([newAge,newName], [oldAge, oldName])=>{
  console.log("年齡new:", newAge, "年齡old:", oldAge); 
  console.log("名稱new:", newName,"年齡old:", oldName);
},);

// 如果監聽多個物件,第一個函式返回一個陣列,
//陣列中表示監聽的值  ()=>[state.value,   person.name ]

// 第二個匿名函式, ([new1,new2],[old1,old2])=>{ }

watch去監聽路由

watch(
  () => route.fullPath,
  (n, o) => {
	 console.log('監聽路由')
	 console.log('new:' + n + ',old:' + o)
  }
)

watch 的第三個引數 deep:true, immediate: true

watch(() => state.value, (newValue, oldValue) => {
  console.log("新值:", newValue, "老值:", oldValue); 
},{ deep: true, immediate: true } );

deep: true 表示開啟深度監聽。
immediate: true 無論資料是否發生變化,資料預設執行一次

在開啟immediate: true。如何值沒有發生變化,
newValue是初始值
oldValue就是 undefined

如何watch監聽

有些時候,當我們監聽到資料發生變化後。可能就不需要再次進行監聽了。
這個時候我們可以取消監聽。
將watch 賦值給一個變數。
let stopWatch=watch(虛擬碼);
   
然後需要取消的時候再次呼叫一次就可以了
stopWatch()
看下面的程式碼,當我點選取消監聽按鈕的時候。
就算資料發生變化,watch也會對該資料進行監聽了

stop 停止監聽watch的監聽

<template>
 <div>
 <div class="bg">
	 {{ person }}
 </div>
 <a-button @click="changeValue">值發生變化了</a-button>
 <a-button @click="cancelHander">取消監聽</a-button>
 </div>
</template>
<script lang="ts">
import { defineComponent, reactive, watch } from 'vue';
export default defineComponent({
  setup() {
   let  person=reactive({
      name:'zs'
   })
   let changeValue=()=>{
      person.name='lisi'
   }
   // 修改age值時會觸發 watch的回撥
   let stopWatch=watch(
      () => person.name,   //監聽state中的age
      (newValue, oldValue) => {
         console.log("新值:", newValue, "老值:", oldValue);
      }
   );
   // 停止watch監聽
   let cancelHander=()=>{
      stopWatch()
   }
   return {
      cancelHander,
      person,
      changeValue,
   };
  },
});
</script>

watchEffect的引入

還有一個監聽函式watchEffect, 
在我看來watch已經能滿足監聽的需求,
為什麼還要有watchEffect呢?
雖然我沒有 get 到它的必要性,
但是還是要介紹一下watchEffect,首先看看它的使用和watch究竟有何不同。
let  person=reactive({
  name:'zs'
})

let state=ref(100)

setInterval(()=>{
  person.name='我是李四',
  state.value=1000
},1000)

// 修改age值時會觸發 watch的回撥
watchEffect(()=>{
	 console.log('state的變化後的值', state.value);
	 console.log('state的變化後的值', person.name);
} );

watchEffect發生的現象

執行結果首先列印一次state和name;然後隔一秒後,列印state和name值。
從上面的程式碼可以看出, 並沒有像watch一樣需要先傳入依賴,
watchEffect會自動收集依賴, 只要指定一個回撥函式。
在元件初始化時, 會先執行一次來收集依賴, 然後當收集到的依賴中資料發生變化時, 
就會再次執行回撥函式。所以總結對比如下:

watchEffect 不需要手動傳入依賴
watchEffect 會先執行一次用來自動收集依賴
watchEffect 無法獲取到變化前的值, 只能獲取變化後的值

相關文章