Vue中有三種響應式數據:props,data,computed,它們都會在特定的條件下更新視圖。但是有些時候如果需要對一個實例屬性進行監視,並在該屬性的值發生變化時執行一些操作,則可以使用Vue的watch功能。而在Vue 3中,相比於watch,watchEffect是一個更加強大、更加靈活的監視選項,它可以自動追蹤響應式變化,並立即執行傳入的函數。
一、Vue WatchEffect概述
WatchEffect在Vue 3中是一個響應式工具函數,它可以執行一個函數並追蹤其中用到的響應式依賴,並在任何該依賴發生改變的時候重新運行這個函數。WatchEffect用於監視一個響應式對象,以便在其屬性變化時執行一些操作。
下面是watchEffect的基本語法:
watchEffect(effect: Function, options: WatchEffectOptions): StopHandle
其中effect為一個函數,在函數中可以訪問響應式屬性,如下面的代碼所示:
import { reactive, watchEffect } from 'vue'
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(state.count)
})
上面代碼中,我們監聽了state對象中count這個屬性的值的變化,並在控制台輸出變化後的新值。
二、WatchEffect處理對象
WatchEffect可以處理多種類型的對象,在這些不同類型的對象中,WatchEffect會自動跟蹤其中任何數據屬性的變化。
1、處理數組
下面是WatchEffect如何處理數組:
import { reactive, watchEffect } from 'vue'
const state = reactive({
todos: [
{ text: 'Learn Vue', done: false },
{ text: 'Learn Vuex', done: false },
{ text: 'Learn Vue Router', done: false }
]
})
watchEffect(() => {
state.todos.forEach(todo => {
console.log(todo.text)
})
})
在上面的代碼中,我們監聽todos數組中每個對象的text屬性,並在控制台輸出text屬性的值。
2、處理嵌套對象
WatchEffect能夠處理嵌套對象,當裡面的屬性發生改變時,監聽函數就會重新運行。
import { reactive, watchEffect } from 'vue'
const state = reactive({
person: {
name: 'Tom',
age: 20,
address: {
city: 'New York',
state: 'NY'
}
}
})
watchEffect(() => {
console.log(state.person.address.city)
})
上面代碼中,我們監聽state對象中嵌套的person對象的address屬性中的city屬性,當city屬性值發生變化時,監聽函數將重新運行。
三、WatchEffect特徵
WatchEffect與watch有以下幾個不同點:
1、WatchEffect是一個自動地、即時地追蹤響應式依賴,並在任何該依賴發生改變的時候重新運行這個函數;而watch是一個手動地監測特定數據的變化。
2、WatchEffect函數不接收特定的數據,而是通過調用響應式對象中所有數據的getter來嘗試捕獲所依賴的數據;watch則需要通過一個計算函數來確定它所依賴的特定數據,並在每個數據變化時觸發回調。
3、WatchEffect返回一個停止函數,該函數可用於停止監視;watch則返回一個取消監聽的函數。
下面我們來看一個具體的例子,使用watchEffect實現一個簡單的計數器:
import { reactive, watchEffect } from 'vue'
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(`Count: ${state.count}`)
})
上面的代碼中,我們定義了一個響應式的數據對象state,其中包含一個count屬性,然後使用watchEffect監聽state.count,當count屬性的值改變時,控制台會輸出最新的count值。
四、WatchEffect響應式的局限性
雖然WatchEffect可以處理多種類型的對象,包括對象、嵌套對象和數組,但是WatchEffect並不是完美的。在某些情況下,WatchEffect可能無法自動追蹤響應式變化。下面是一些WatchEffect無法處理的情況:
1、普通對象屬性
WatchEffect只會追蹤響應式對象的值。 如果在響應式對象中放置了一個非響應式對象,則 WatchEffect 將無法監聽到該對象屬性的變化。
2、動態添加屬性或刪除屬性
在Vue 3中,已經可以動態添加/刪除對象屬性和數組元素,這些屬性和元素將是非響應式的。這意味著,當我們使用WatchEffect監聽對象屬性或數組元素時,添加或刪除屬性/元素將不會觸發監聽函數。
五、WatchEffect高級特性
WatchEffect有一些高級用法,如:
1、WatchEffect函數和具體依賴的區別
WatchEffect可以監視計算屬性或組合屬性,但WatchEffect不會檢查具體的依賴,而是對數據進行一次靜態分析。下面是一個例子:
const state = reactive({
firstName: 'First Name',
lastName: 'Last Name'
})
watchEffect(() => {
console.log(`Full Name: ${state.firstName} ${state.lastName}`)
})
上面代碼中,我們用WatchEffect監測state對象的firstName和lastName屬性。如果我們在輸出語句中使用計算屬性fullName代替firstName和lastName,如下所示:
const state = reactive({
firstName: 'First Name',
lastName: 'Last Name'
})
watchEffect(() => {
const fullName = `${state.firstName} ${state.lastName}`
console.log(`Full Name: ${fullName}`)
})
這將使WatchEffect無法檢測fullName的依賴關係,因為它不知道fullName是由哪些數據組成的。這將導致我們在WatchEffect中不得不寫更多的響應式數據。
2、WatchEffect處理非同步更新
有些情況下,WatchEffect監聽的響應式數據的更新是非同步的。在這種情況下,如果我們需要在WatchEffect監聽回調函數中使用非同步更新的響應式數據,需要使用Vue提供的「界面刷新同步保證」機制,即「$nextTick()」函數。
下面是一個例子,演示了如何處理非同步更新:
import { reactive, watchEffect } from 'vue'
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(`Count: ${state.count}`)
Vue.nextTick().then(() => {
console.log(`Count (after DOM update): ${state.count}`)
})
})
setInterval(() => {
state.count++
}, 1000)
上面的代碼中,我們用watchEffect按秒監測state.count的變化,每一次變化都輸出count的新值。為了處理非同步更新,我們使用了Vue提供的「$nextTick()」方法,它會在下一次DOM更新之後執行回調函數,以確保我們能夠獲取到更新後的值。
六、結論
Vue WatchEffect提供了一種更加靈活和高效的方式,能夠方便地追蹤響應式變化,並立即執行傳入的函數。WatchEffect處理對象的能力很強,它能夠處理多種類型的響應式依賴,包括對象、嵌套對象和數組。 WatchEffect的高級特性包括能夠監視計算屬性和處理非同步更新。儘管WatchEffect有一些局限性,但它依然是Vue 3中響應式的一個非常強大的工具。
原創文章,作者:SXOAT,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/334139.html