1. 程式人生 > 程式設計 >如何理解Vue中computed和watch的區別

如何理解Vue中computed和watch的區別

概述

我們在 vue 專案中多多少少都會有用到 computed 和 watch,這兩個看似都能實現對資料的監聽,但還是有區別。所以以下通過一個小栗子來理解一下這兩者的區別。

computed 計算屬性

計算屬性基於 data 中宣告過或者父元件傳遞的 props 中的資料通過計算得到的一個新值,這個新值只會根據已知值的變化而變化,簡言之:這個屬性依賴其他屬性,由其他屬性計算而來的。

<p>姓名:{{ fullName }}</p>
... ...
data: {
    firstName: 'David',lastName: 'Beckham'
},computed:http://www.cppcns.com
{ fullName: function() { //方法的返回值作為屬性值 return this.firstName + ' ' + this.lastName } }

在 computed 屬性物件中定義計算屬性的方法,和取data物件裡的資料屬性一樣以屬性訪問的形式呼叫,即在頁面中使用 {{ 方法名 }} 來顯示計算的結果。

注:計算屬性 fullName 不能在 data 中定義,而計算屬性值的相關已知值在data中;

如果 fullName 在 data 中定義了會報錯如下圖:

如何理解Vue中computed和watch的區別

因為如果 computed 屬性值是一個函式,那麼預設會走get方法,必須要有一個返回值,函式的返回值就是屬性的屬性值。計算屬性定義了 fullName 並返回對應的結果給這個變數,變數不可被重複定義和賦值。

在官方文件中,還強調了 computed 一個重要的特點,就是 computed 帶有快取功能。比如我在頁面中多次顯示 fullName:

<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
... ... 

comCILjVipputed: {
    fullName: function () {
         console.log('computed') // 在控制檯只打印了一次
         return this.firstName + ' ' + this.lastName
    }
}

我們知道 computed 內定義的 function 只執行一次,僅當初始化顯示或者相關的 data、props 等屬性資料發生變化的時候呼叫;

而 computed 屬性值預設會快取計算結果,計算屬性是基於它們的響應式依賴進行快取的;

只有當 computed 屬性被使用後,才會執行 computed 的程式碼,在重複的呼叫中,只要依賴資料不變,直接取快取中的計算結果。只有依賴型資料發生改變,computed 才會重新計算。

計算屬性的高階:

在computed 中的屬性都有一個 get 和一個set方法,當資料變化時,呼叫 set 方法。下面我們通過計算屬性的 getter/setter 方法來實現對屬性資料的顯示和監視,即雙向繫結。

computed: {
    fullName: {
        get() { //讀取當前屬性值的回撥,根據相關的資料計算並返回當前屬性的值
            return this.firstName + ' ' + this.lastName
        },set(val) { // 當屬性值發生改變時回撥,更新相關的屬性資料,val就是fullName的最新屬性值
            const names = val ? val.split(' ') : [];
            this.firstName = names[0]
            this.lastName = names[1]
        }
    }
}

watch 監聽屬性

通過 vm 物件的 $watchwww.cppcns.com() 或 watch 配置來監聽 Vue 例項上的屬性變化,或某些特定資料的變化,然後執行某些具體的業務邏輯操作。當屬性變化時,回撥函式自動呼叫,在函式內部進行計算。其可以監聽的資料來源:data,props,computed 內的資料。

以上示例通過 watch 來實現:

watch: {
    // 監聽 data 中的 firstName,www.cppcns.com如果發生了變化,就把變化的值給 data 中的 fullName, val 就是 firstName 的最新值
    firstName: function(val) { 
        this.fullName = val + ' ' + this.lastName
    },lastName: function(val) {
        this.fullName = this.firstName + ' ' + val
    }    
}
// 由上可以看出 watch 要監聽兩個資料,而且程式碼是同類型的重複的,所以相比用 computed 更簡潔

注:監聽函式有兩個引數,第一個引數是最新的值,第二個引數是輸入之前的值,順序一定是新值,舊值,如果只寫一個引數,那就是最新屬性值。

在使用時選擇 watch 還是 computed,還有一個參考點就是官網說的:當需要在資料變化時執行非同步或開銷較大的操作時,watch方式是最有用的。所以 watch 一定是支援非同步的。

上面僅限監聽簡單資料型別,監聽複雜資料型別就需要用到深度監聽 deep。

deep:為了發現物件內部值的變化,可以在選項引數中指定 deep: true。注意監聽陣列的變更不需要這麼做。

data: {
    fullName: {
        firstName: 'David',lastName: 'Beckham'
    }
},watch: {
    fullName: {
        handler(newVal,oldVal) {
            console.log(newVal);
            console.log(oldVal);
        },deep: true
    }
}

以上列印結果:

如何理解Vue中computed和watch的區別

打印出來的 newVal 和 oldVal 值是一樣的,所以深度監聽雖然可以監聽到物件的變化,但是無法監聽到物件裡面哪個具體屬性的變化。這是因為它們的引用指向同一個物件/陣列。Vue 不會保留變更之前值的副本。[ vm.$watch 深度監聽 ]

若果要監聽物件的單個屬性的變化,有兩種方法:

1. 直接監聽物件的屬性

watch:{
    fullName.firstName: function(newVal,oldVal){
        console.log(newVal,oldVal);
    }
}

2. 與 computed 屬性配合使用,computed 返回想要監聽的屬性值,watch 用來監聽

computed: {
    firstNameChange() {
    return this.fullName.firstName
    }
},watch: {
    firstNameChange() {
        console.log(this.fullName)
    }
}

總結

watch和computed都是以Vue的依賴追蹤機制為基礎的,當某一個依賴型資料(依賴型資料:簡單理解即放在 data 等物件下的例項資料)發生變化的時候,所有依賴這個資料的相關資料會自動發生變化,即自動呼叫相關的函式,來實現資料的變動。

當依賴的值變化時,在watch中,是可以做一些複雜的操作的,而computed中的依賴,僅僅是一個值依賴於另一個值,是值上的依賴。

應用場景:

computed:用於處理複雜的邏輯運算;一個數據受一個或多個數據影響;用來處理watch和methods無法處理的,或處理起來不方便的情況。例如處理模板中的複雜表示式、購物車裡面的商品數量和總金額之間的變化關係等。

watch:用來處理當一個屬性發生變化時,需要執行某些具體的業務邏輯操作,或要在資料變化時執行非同步或開銷較大的操作;一個數據改變影響多個數據程式設計客棧。例如用來監控路由、inpurt 輸入框值的特殊處理等。

區別:  

computed

  • 初始化顯示或者相關的 data、props 等屬性資料發生變化的時候呼叫;
  • 計算屬性不在 data 中,它是基於data 或 props 中的資料通過計算得到的一個新值,這個新值根據已知值的變化而變化;
  • 在 computed 屬性物件中定義計算屬性的方法,和取data物件裡的資料屬性一樣,以屬性訪問的形式呼叫;
  • 如果 computed 屬性值是函式,那麼預設會走 get 方法,必須要有一個返回值,函式的返回值就是屬性的屬性值;
  • computed 屬性值預設會快取計算結果,在重複的呼叫中,只要依賴資料不變,直接取快取中的計算結果,只有依賴型資料發生改變,computed 才會重新計算;
  • 在computed中的,屬性都有一個 get 和一個 set 方法,當資料變化時,呼叫 set 方法。

watch

  • 主要用來監聽某些特定資料的變化,從而進行某些具體的業務邏輯操作,可以看作是 computed 和 methods 的結合體;
  • 可以監聽的資料來源:data,props,computed內的資料;
  • watch支援非同步;
  • 不支援快取,監聽的資料改變,直接會觸發相應的操作;
  • 監聽函式有兩個引數,第一個引數是最新的值,第二個引數是輸入之前的值,順序一定是新值,舊值。

以上就是如何理解Vue中computed和watch的區別的詳細內容,更多關於Vue的資料請關注我們其它相關文章!