vue中computed與watch的區(qū)別

computed (計算屬性)

  1. 支持緩存,只有依賴數(shù)據(jù)發(fā)生改變,才會重新進(jìn)行計算
  2. 不支持異步,當(dāng)computed內(nèi)有異步操作時無效,無法監(jiān)聽數(shù)據(jù)的變化
  3. computed 屬性值會默認(rèn)走緩存,計算屬性是基于它們的響應(yīng)式依賴進(jìn)行緩存的,也就是基于data中聲明過或者父組件傳遞的props中的數(shù)據(jù)通過計算得到的值
  4. 如果一個屬性是由其他屬性計算而來的,這個屬性依賴其他屬性,是一個多對一或者一對一,一般用computed
  5. 如果computed屬性屬性值是函數(shù),那么默認(rèn)會走get方法;函數(shù)的返回值就是屬性的屬性值;在computed中的,屬性都有一個get和一個set方法,當(dāng)數(shù)據(jù)變化時,調(diào)用set方法。
<template>
    <div>
        <p>{{fullName}}</p>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "",
    data() {
        return {
            firstName: '張',
            lastName: '三'
        }
    },
    computed: {
        fullName() {
            return this.firstName + ' ' + this.lastName
        }
    }
}
</script>

getter與setter:

通過getter\setter實現(xiàn)對屬性數(shù)據(jù)的顯示和監(jiān)視,計算屬性存在緩存,多次讀取只執(zhí)行一次getter計算

<template>
    <div>
        <p>{{fullName}}</p>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "",
    data() {
        return {
            firstName: '張',
            lastName: '三'
        }
    },
    computed: {
        fullName: {
            // getter  對屬性數(shù)據(jù)的顯示
            get() {// 回調(diào)函數(shù) 當(dāng)需要讀取當(dāng)前屬性值時執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計算并返回當(dāng)前屬性的值
                return this.firstName + ' ' + this.lastName
            },
            // setter  對屬性數(shù)據(jù)的監(jiān)聽
            set(val) { // 監(jiān)聽當(dāng)前屬性值的變化,當(dāng)屬性值發(fā)生變化時執(zhí)行,更新相關(guān)的屬性數(shù)據(jù)
                // val就是fullName的最新屬性值
                console.log(val)
                const names = val.split(' ');
                console.log(names)
                this.firstName = names[0];
                this.lastName = names[1];
            }
        }
    }
}
</script>

watch(監(jiān)聽屬性)

  1. 不支持緩存,數(shù)據(jù)變,直接會觸發(fā)相應(yīng)的操作;
  2. watch支持異步;
  3. 監(jiān)聽的函數(shù)接收兩個參數(shù),第一個參數(shù)是最新的值;第二個參數(shù)是輸入之前的值;
  4. 當(dāng)一個屬性發(fā)生變化時,需要執(zhí)行對應(yīng)的操作;一對多;
  5. 監(jiān)聽數(shù)據(jù)必須是data中聲明過或者父組件傳遞過來的props中的數(shù)據(jù),當(dāng)數(shù)據(jù)變化時,觸發(fā)其他操作,函數(shù)有兩個參數(shù),
      immediate:組件加載立即觸發(fā)回調(diào)函數(shù)執(zhí)行,
      deep: 深度監(jiān)聽,為了發(fā)現(xiàn)對象內(nèi)部值的變化,復(fù)雜類型的數(shù)據(jù)時使用,例如數(shù)組中的對象內(nèi)容的改變,注意監(jiān)聽數(shù)組的變動不需要這么做。注意:deep無法監(jiān)聽到數(shù)組的變動和對象的新增,參考vue數(shù)組變異,只有以響應(yīng)式的方式觸發(fā)才會被監(jiān)聽到。
new Vue({
    el: '#id',
    template: `<div>
        // ...
    </div>`,
    data: {
        firstName: 'Leo',
        lastName: 'Alan',
        obj1: {
            a: 0
        }
    },
    watch: {
        // 監(jiān)聽firstName,當(dāng)firstName發(fā)生變化時就會執(zhí)行該函數(shù)
        firstName () {
            // 執(zhí)行需要的操作...
            // 注:初始化不會執(zhí)行,只有當(dāng)被監(jiān)聽的值(firstName)發(fā)生變化時才會執(zhí)行
        },

        // 監(jiān)聽lastName
        lastName: {
            handler (newName, oldName) {
                // 執(zhí)行需要的操作...
            },
            immediate: true // true: 初始化時就會先執(zhí)行一遍該監(jiān)聽對應(yīng)的操作    
        },
        obj1: {
            handler () {
                // 執(zhí)行需要的操作...
            },
            deep: true // 該屬性默認(rèn)值為false. 
            // 當(dāng)被監(jiān)聽的值是對象,只有deep為true時,對應(yīng)屬性的值(obj1.a)發(fā)生變化時才能觸發(fā)監(jiān)聽事件,但是這樣非常消耗性能
        },

        // 監(jiān)聽對象具體的屬性, deep就不需要設(shè)置為true了
        'obj1.a': {
            handler () {
                // 執(zhí)行需要的操作...
            }
        }

    }
})

immediate(立即監(jiān)聽)

<template>
    <div>
        <p>FullName: {{fullName}}</p>
        <p>FirstName: <input type="text" v-model="firstName"></p>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "",
    data() {
        return {
            firstName: '張',
            lastName: '三',
            fullName: ''
        }
    },
    watch: {
        firstName: {
            handler(newVal, oldVal) {
                this.fullName = newVal + this.lastName;
            },
            // 代表在wacth里聲明了name這個方法之后立即先去執(zhí)行handler方法
            immediate: true
        }
    }
}
</script>

deep(深度監(jiān)聽)

由于 Vue 不能檢測到對象屬性的添加或刪除,這時候deep屬性就派上用場了!

<template>
    <div>
        <p>obj.a: {{obj.a}}</p>
        <p>obj.a: <input type="text"
                   v-model="obj.a"></p>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "",
    data() {
        return {
            obj: {
                a: 123
            }
        }
    },
    watch: {
        obj: {
            handler(newVal, oldVal) {
                console.log('obj.a changed');
            },
            // 深度監(jiān)聽對象
            deep: true
        }
    }
}
</script>

deep的意思就是深入觀察,監(jiān)聽器會一層層的往下遍歷,給對象的所有屬性都加上這個監(jiān)聽器,但是這樣性能開銷就會非常大了,任何修改obj里面任何一個屬性都會觸發(fā)這個監(jiān)聽器里的 handler。
優(yōu)化,我們可以是使用<font color=#FF0000>字符串形式監(jiān)聽</font>。

<template>
    <div>
        <p>obj.a: {{obj.a}}</p>
        <p>obj.a: <input type="text"
                   v-model="obj.a"></p>
    </div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "",
    data() {
        return {
            obj: {
                a: 123
            }
        }
    },
    watch: {
        'obj.a': { // 字符串形式監(jiān)聽
            handler(newVal, oldVal) {
                console.log('obj.a changed');
            },
            // deep: true
        }
    }
}
</script>

注意: 不要在computed和watch中修改被依賴(或者被監(jiān)聽)的值,這樣可能會導(dǎo)致無限循環(huán)
注意: 不要在computed和watch中修改被依賴(或者被監(jiān)聽)的值,這樣可能會導(dǎo)致無限循環(huán)
注意: 不要在computed和watch中修改被依賴(或者被監(jiān)聽)的值,這樣可能會導(dǎo)致無限循環(huán)

作者:貓老板的豆
鏈接:https://juejin.im/post/5b961773f265da0a9e52f0e3
來源:csdn
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容