vue中的計(jì)算屬性和偵聽(tīng)器

計(jì)算屬性概念

模板內(nèi)的表達(dá)式非常便利,但是設(shè)計(jì)它們的初衷是用于簡(jiǎn)單運(yùn)算的。在模板中放入太多的邏輯會(huì)讓模板過(guò)重且難以維護(hù)。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在這個(gè)地方,模板不再是簡(jiǎn)單的聲明式邏輯。你必須看一段時(shí)間才能意識(shí)到,這里是想要顯示變量 message 的翻轉(zhuǎn)字符串。當(dāng)你想要在模板中多次引用此處的翻轉(zhuǎn)字符串時(shí),就會(huì)更加難以處理。

所以,對(duì)于任何復(fù)雜邏輯,你都應(yīng)當(dāng)使用計(jì)算屬性

簡(jiǎn)單的理解為:

1.計(jì)算屬性其實(shí)就是 Vue 實(shí)例的一個(gè)屬性

2.計(jì)算屬性一般依賴傳統(tǒng)的 Vue 實(shí)例屬性

3.計(jì)算屬性一般是通過(guò)運(yùn)算得到的屬性

計(jì)算屬性的get和set

簡(jiǎn)單的寫(xiě)法

computed: {
  reversedMessage() {
    return this.message.split('').reverse().join('')
  }
}

完整版寫(xiě)法

computed: {
    reversedMessage: {
        get() { //獲取值
           return this.message.split('').reverse().join('')
        },
        set(val) { // set方法:設(shè)置值
         this.message = val.split('').reverse().join('')
        }
    }
}

計(jì)算屬性VS方法

HTML

<p>Reversed message: "{{ reversedMessage() }}"</p>

JS

// 在組件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

計(jì)算屬性是基于它們的依賴進(jìn)行緩存的,只有在它相關(guān)的依賴發(fā)生改變時(shí)才會(huì)重新求值,即計(jì)算屬性會(huì)對(duì)計(jì)算出來(lái)的結(jié)果進(jìn)行緩存,這就意味著只要 message 還沒(méi)有發(fā)生改變,多次訪問(wèn) reversedMessage 計(jì)算屬性會(huì)立即返回之前的計(jì)算結(jié)果,而不必再次執(zhí)行函數(shù)

方法是每次重新渲染時(shí),調(diào)用方法將總會(huì)再次執(zhí)行函數(shù),開(kāi)銷(xiāo)比較大

我們?yōu)槭裁葱枰彺妫?/p>

假設(shè)我們有一個(gè)性能開(kāi)銷(xiāo)比較大的計(jì)算屬性 A,它需要遍歷一個(gè)巨大的數(shù)組并做大量的計(jì)算。然后我們可能有其他的計(jì)算屬性依賴于 A 。如果沒(méi)有緩存,我們將不可避免的多次執(zhí)行 A 的 getter!如果你不希望有緩存,請(qǐng)用方法來(lái)替代
計(jì)算屬性 vs 偵聽(tīng)屬性

watch
放在 data 中的對(duì)象,一旦發(fā)生改變就會(huì)執(zhí)行相應(yīng)的操作,當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷(xiāo)較大的操作時(shí),這個(gè)方式是最有用的

<div>
  <p>FullName: {{fullName}}</p>
  <p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
  el: '#root',
  data: {
    firstName: 'Joy',
    lastName: 'lqy',
    fullName: ''
  },
  watch: {
    firstName(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    }
  } 
})

watch 中的對(duì)象在 data 中已經(jīng)定義了,當(dāng)我們輸入firstName后, watch監(jiān)聽(tīng)每次修改變化的新值,然后計(jì)算輸出fullName。也就是上面的代碼中,fullName 一開(kāi)始被渲染出來(lái)的時(shí)候是空值,如下所示:

image

watch的高級(jí)用法

handler方法和immediate屬性

如上所述,一開(kāi)始被渲染出來(lái)的時(shí)候,fullName是空值,如果想要一開(kāi)始就讓最初綁定的值執(zhí)行該怎么辦尼?別急,我們只需要給firstName綁定一個(gè)handler方法,之前我們寫(xiě)的watch方法其實(shí)默認(rèn)寫(xiě)的就是這個(gè)handler,Vue.js會(huì)去處理這個(gè)邏輯,最終編譯出來(lái)其實(shí)就只這個(gè)handler,設(shè)置immediate:true代表如果在 wacth 里聲明了 firstName 之后,就會(huì)立即先去執(zhí)行里面的handler方法,如果為 false就跟我們以前的效果一樣,不會(huì)在綁定的時(shí)候就執(zhí)行

修改后的代碼如下:

 watch: {
    firstName: {
        handler(newName, oldName) {
            this.fullName = newName + ' ' + this.lastName;
        },
        // 代表在wacth里聲明了firstName這個(gè)方法之后立即先去執(zhí)行handler方法
        immediate: true
    }
}

結(jié)果如下:


image
deep屬性

deep,默認(rèn)值為false,代表是否深度監(jiān)聽(tīng),

總的來(lái)說(shuō),計(jì)算屬性傾向于格式化/處理當(dāng)前的數(shù)據(jù),而 watch 傾向于執(zhí)行數(shù)據(jù)變化需要進(jìn)行的操作

注銷(xiāo)watch

為什么要注銷(xiāo) watch?因?yàn)槲覀兊慕M件是經(jīng)常要被銷(xiāo)毀的,比如我們跳一個(gè)路由,從一個(gè)頁(yè)面跳到另外一個(gè)頁(yè)面,那么原來(lái)的頁(yè)面的watch 其實(shí)就沒(méi)用了,這時(shí)候我們應(yīng)該注銷(xiāo)掉原來(lái)頁(yè)面的 watch 的,不然的話可能會(huì)導(dǎo)致內(nèi)置溢出。好在我們平時(shí) watch 都是寫(xiě)在組件的選項(xiàng)中的,他會(huì)隨著組件的銷(xiāo)毀而銷(xiāo)毀。

const app = new Vue({
  template: '<div id="root">{{text}}</div>',
  data: {
    text: 0
  },
  watch: {
    text(newVal, oldVal){
      console.log(`${newVal} : ${oldVal}`);
    }
  }
});

但是,如果我們使用下面這樣的方式寫(xiě) watch,那么就要手動(dòng)注銷(xiāo)了,這種注銷(xiāo)其實(shí)也很簡(jiǎn)單

const unWatch = app.$watch('text', (newVal, oldVal) => {
  console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手動(dòng)注銷(xiāo)watch

app.$watch調(diào)用后會(huì)返回一個(gè)值,就是unWatch方法,你要注銷(xiāo) watch 只要調(diào)用unWatch方法就可以了。

參考

計(jì)算屬性和偵聽(tīng)器
Vue.js中偵聽(tīng)器(watch)的高級(jí)用法

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

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

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