溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue中computed和watch的區(qū)別有哪些

發(fā)布時間:2021-05-12 10:31:11 來源:億速云 閱讀:261 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下Vue中computed和watch的區(qū)別有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

概述

我們在 Vue 項目中多多少少都會有用到 computed 和 watch,這兩個看似都能實現(xiàn)對數(shù)據(jù)的監(jiān)聽,但還是有區(qū)別。所以以下通過一個小栗子來理解一下這兩者的區(qū)別。

computed 計算屬性

計算屬性基于 data 中聲明過或者父組件傳遞的 props 中的數(shù)據(jù)通過計算得到的一個新值,這個新值只會根據(jù)已知值的變化而變化,簡言之:這個屬性依賴其他屬性,由其他屬性計算而來的。

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

在 computed 屬性對象中定義計算屬性的方法,和取data對象里的數(shù)據(jù)屬性一樣以屬性訪問的形式調(diào)用,即在頁面中使用 {{ 方法名 }} 來顯示計算的結(jié)果。

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

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

Vue中computed和watch的區(qū)別有哪些

因為如果 computed 屬性值是一個函數(shù),那么默認會走get方法,必須要有一個返回值,函數(shù)的返回值就是屬性的屬性值。計算屬性定義了 fullName 并返回對應(yīng)的結(jié)果給這個變量,變量不可被重復(fù)定義和賦值。

在官方文檔中,還強調(diào)了 computed 一個重要的特點,就是 computed 帶有緩存功能。比如我在頁面中多次顯示 fullName:

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

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

我們知道 computed 內(nèi)定義的 function 只執(zhí)行一次,僅當(dāng)初始化顯示或者相關(guān)的 data、props 等屬性數(shù)據(jù)發(fā)生變化的時候調(diào)用;

而 computed 屬性值默認會緩存計算結(jié)果,計算屬性是基于它們的響應(yīng)式依賴進行緩存的;

只有當(dāng) computed 屬性被使用后,才會執(zhí)行 computed 的代碼,在重復(fù)的調(diào)用中,只要依賴數(shù)據(jù)不變,直接取緩存中的計算結(jié)果。只有依賴型數(shù)據(jù)發(fā)生改變,computed 才會重新計算。

計算屬性的高級:

在computed 中的屬性都有一個 get 和一個set方法,當(dāng)數(shù)據(jù)變化時,調(diào)用 set 方法。下面我們通過計算屬性的 getter/setter 方法來實現(xiàn)對屬性數(shù)據(jù)的顯示和監(jiān)視,即雙向綁定。

computed: {
    fullName: {
        get() { //讀取當(dāng)前屬性值的回調(diào),根據(jù)相關(guān)的數(shù)據(jù)計算并返回當(dāng)前屬性的值
            return this.firstName + ' ' + this.lastName
        },
        set(val) { // 當(dāng)屬性值發(fā)生改變時回調(diào),更新相關(guān)的屬性數(shù)據(jù),val就是fullName的最新屬性值
            const names = val ? val.split(' ') : [];
            this.firstName = names[0]
            this.lastName = names[1]
        }
    }
}

watch 監(jiān)聽屬性

通過 vm 對象的 $watch() 或 watch 配置來監(jiān)聽 Vue 實例上的屬性變化,或某些特定數(shù)據(jù)的變化,然后執(zhí)行某些具體的業(yè)務(wù)邏輯操作。當(dāng)屬性變化時,回調(diào)函數(shù)自動調(diào)用,在函數(shù)內(nèi)部進行計算。其可以監(jiān)聽的數(shù)據(jù)來源:data,props,computed 內(nèi)的數(shù)據(jù)。

以上示例通過 watch 來實現(xiàn):

watch: {
    // 監(jiān)聽 data 中的 firstName,如果發(fā)生了變化,就把變化的值給 data 中的 fullName, val 就是 firstName 的最新值
    firstName: function(val) { 
        this.fullName = val + ' ' + this.lastName
    },
    lastName: function(val) {
        this.fullName = this.firstName + ' ' + val
    }    
}
// 由上可以看出 watch 要監(jiān)聽兩個數(shù)據(jù),而且代碼是同類型的重復(fù)的,所以相比用 computed 更簡潔

注:監(jiān)聽函數(shù)有兩個參數(shù),第一個參數(shù)是最新的值,第二個參數(shù)是輸入之前的值,順序一定是新值,舊值,如果只寫一個參數(shù),那就是最新屬性值。

在使用時選擇 watch 還是 computed,還有一個參考點就是官網(wǎng)說的:當(dāng)需要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作時,watch方式是最有用的。所以 watch 一定是支持異步的。

上面僅限監(jiān)聽簡單數(shù)據(jù)類型,監(jiān)聽復(fù)雜數(shù)據(jù)類型就需要用到深度監(jiān)聽 deep。

deep:為了發(fā)現(xiàn)對象內(nèi)部值的變化,可以在選項參數(shù)中指定 deep: true。注意監(jiān)聽數(shù)組的變更不需要這么做。

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

以上打印結(jié)果:

Vue中computed和watch的區(qū)別有哪些

打印出來的 newVal 和 oldVal 值是一樣的,所以深度監(jiān)聽雖然可以監(jiān)聽到對象的變化,但是無法監(jiān)聽到對象里面哪個具體屬性的變化。這是因為它們的引用指向同一個對象/數(shù)組。Vue 不會保留變更之前值的副本。[ vm.$watch 深度監(jiān)聽 ]

若果要監(jiān)聽對象的單個屬性的變化,有兩種方法:

1. 直接監(jiān)聽對象的屬性

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

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

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

總結(jié)

watch和computed都是以Vue的依賴追蹤機制為基礎(chǔ)的,當(dāng)某一個依賴型數(shù)據(jù)(依賴型數(shù)據(jù):簡單理解即放在 data 等對象下的實例數(shù)據(jù))發(fā)生變化的時候,所有依賴這個數(shù)據(jù)的相關(guān)數(shù)據(jù)會自動發(fā)生變化,即自動調(diào)用相關(guān)的函數(shù),來實現(xiàn)數(shù)據(jù)的變動。

當(dāng)依賴的值變化時,在watch中,是可以做一些復(fù)雜的操作的,而computed中的依賴,僅僅是一個值依賴于另一個值,是值上的依賴。

應(yīng)用場景:

computed:用于處理復(fù)雜的邏輯運算;一個數(shù)據(jù)受一個或多個數(shù)據(jù)影響;用來處理watch和methods無法處理的,或處理起來不方便的情況。例如處理模板中的復(fù)雜表達式、購物車里面的商品數(shù)量和總金額之間的變化關(guān)系等。

watch:用來處理當(dāng)一個屬性發(fā)生變化時,需要執(zhí)行某些具體的業(yè)務(wù)邏輯操作,或要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作;一個數(shù)據(jù)改變影響多個數(shù)據(jù)。例如用來監(jiān)控路由、inpurt 輸入框值的特殊處理等。

區(qū)別:  

computed

  • 初始化顯示或者相關(guān)的 data、props 等屬性數(shù)據(jù)發(fā)生變化的時候調(diào)用;

  • 計算屬性不在 data 中,它是基于data 或 props 中的數(shù)據(jù)通過計算得到的一個新值,這個新值根據(jù)已知值的變化而變化;

  • 在 computed 屬性對象中定義計算屬性的方法,和取data對象里的數(shù)據(jù)屬性一樣,以屬性訪問的形式調(diào)用;

  • 如果 computed 屬性值是函數(shù),那么默認會走 get 方法,必須要有一個返回值,函數(shù)的返回值就是屬性的屬性值;

  • computed 屬性值默認會緩存計算結(jié)果,在重復(fù)的調(diào)用中,只要依賴數(shù)據(jù)不變,直接取緩存中的計算結(jié)果,只有依賴型數(shù)據(jù)發(fā)生改變,computed 才會重新計算;

  • 在computed中的,屬性都有一個 get 和一個 set 方法,當(dāng)數(shù)據(jù)變化時,調(diào)用 set 方法。

watch

  • 主要用來監(jiān)聽某些特定數(shù)據(jù)的變化,從而進行某些具體的業(yè)務(wù)邏輯操作,可以看作是 computed 和 methods 的結(jié)合體;

  • 可以監(jiān)聽的數(shù)據(jù)來源:data,props,computed內(nèi)的數(shù)據(jù);

  • watch支持異步;

  • 不支持緩存,監(jiān)聽的數(shù)據(jù)改變,直接會觸發(fā)相應(yīng)的操作;

  • 監(jiān)聽函數(shù)有兩個參數(shù),第一個參數(shù)是最新的值,第二個參數(shù)是輸入之前的值,順序一定是新值,舊值。

vue是什么

Vue是一套用于構(gòu)建用戶界面的漸進式JavaScript框架,Vue與其它大型框架的區(qū)別是,使用Vue可以自底向上逐層應(yīng)用,其核心庫只關(guān)注視圖層,方便與第三方庫和項目整合,且使用Vue可以采用單文件組件和Vue生態(tài)系統(tǒng)支持的庫開發(fā)復(fù)雜的單頁應(yīng)用。

以上是“Vue中computed和watch的區(qū)別有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI