vue 核心之一 計(jì)算屬性computed 和偵聽(tīng)屬性watch
對(duì)于很多初學(xué)vue的初級(jí)前端開(kāi)發(fā)工程而言,在了解了vue雙向數(shù)據(jù)綁定v-model、模板語(yǔ)法、實(shí)例創(chuàng)建等基礎(chǔ)的知識(shí)之后,對(duì)于一些復(fù)雜的數(shù)據(jù)操作還無(wú)從下手。
首先,什么是計(jì)算屬性?
在vue官方文檔中,對(duì)計(jì)算屬性的初衷是由于模板內(nèi)部的表達(dá)式雖然已經(jīng)很便利,但是它只能進(jìn)行簡(jiǎn)單的運(yùn)算,而且面對(duì)復(fù)雜邏輯的時(shí)候,模板過(guò)重并且難以維護(hù),所以官方給的建議是對(duì)于任何復(fù)雜的邏輯都應(yīng)當(dāng)使用計(jì)算屬性。
那么,我們?yōu)槭裁匆褂糜?jì)算屬性呢?它到底有什么好處,可以給我們帶來(lái)哪些便利呢?
我們一起來(lái)看下以下代碼
{{ message.split('').reverse().join('') }}
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
}
})
對(duì)于初學(xué)著來(lái)說(shuō),如果要拆分對(duì)message進(jìn)行處理或者其他的復(fù)雜操作,我們可能會(huì)想到上面這種形式去處理,但是如果說(shuō),要實(shí)行for循環(huán)呢?
有人會(huì)說(shuō),我可以在`methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}```
這樣寫(xiě),
但是,如果我需要這個(gè)message動(dòng)態(tài)的去改變呢?
為了適應(yīng)復(fù)雜的業(yè)務(wù)邏輯,計(jì)算屬性cumputed就橫空出世了,雖然cumputed和methods可以完成同樣的事情,但是copmputed是基于依賴(lài)進(jìn)行緩存的,然而methods需要每一次的去進(jìn)行計(jì)算。
我們可以改寫(xiě)這個(gè)例子
```<div id="app">
<h1>{{ reversedMessage}}"</h1>
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello'
},
computed: {
// 計(jì)算屬性的 getter
reversedMessage: function () {
// `this` 指向 app 實(shí)例
return this.message.split('').reverse().join('')
}
}
})```
我們可以將同一函數(shù)定義為一個(gè)方法而不是一個(gè)計(jì)算屬性。兩種方式的最終結(jié)果確實(shí)是完全相同的。然而,不同的是計(jì)算屬性是基于它們的響應(yīng)式依賴(lài)進(jìn)行緩存的。只在相關(guān)響應(yīng)式依賴(lài)發(fā)生改變時(shí)它們才會(huì)重新求值。這就意味著只要 message 還沒(méi)有發(fā)生改變,多次訪(fǎng)問(wèn) reversedMessage 計(jì)算屬性會(huì)立即返回之前的計(jì)算結(jié)果,而不必再次執(zhí)行函數(shù)。此時(shí)你可以動(dòng)態(tài)的去修改message的值,可以動(dòng)態(tài)的看到reversedMessage再動(dòng)態(tài)的更新。
其次:計(jì)算屬性是沒(méi)有setter的,默認(rèn)的情況下只有g(shù)etter
不過(guò)你可以添加一個(gè)setter進(jìn)去。
例子:
<div id="app">{{ allName }}</div>
// 用computed實(shí)現(xiàn)
var vm = new Vue({
el: '#app',
data: {
her: '尼古拉斯趙四',
he: '劉英'
},
computed: {
allName: function () {
get: function () {
return this.her+ ' 的女兒是' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.her= names[0]
this.he= names[names.length - 1]
}
}
}
})
現(xiàn)在運(yùn)行vm.allName時(shí),setter也會(huì)執(zhí)行,vm.her和vm.she也會(huì)被更新
##Watch
**雖然計(jì)算屬性很強(qiáng)大,但是面對(duì)復(fù)雜的業(yè)務(wù)需求和奇特的產(chǎn)品經(jīng)理(雖然很多時(shí)候你都想狠狠地胖揍他一頓)的時(shí)候,我們也需要一個(gè)自定義的偵聽(tīng)器去檢測(cè)數(shù)據(jù)的動(dòng)態(tài)變化,當(dāng)數(shù)據(jù)進(jìn)行異步或者數(shù)據(jù)的開(kāi)銷(xiāo)比較龐大的時(shí)候,這個(gè)時(shí)候watch就顯得比較有用了**
```<div id="app">
<button @click="add">add</button>
<p>點(diǎn)擊次數(shù):{{num}}</p>
</div>
var vm = new Vue({
el: '#app',
data: {
num: 10
},
watch: {
// 監(jiān)聽(tīng)數(shù)據(jù)的變化做出對(duì)應(yīng)的改變,并不會(huì)生成新的屬性
num (val) {
if (val< 5) this.alert()
}
},
methods: {
alert () {
alert('點(diǎn)擊次數(shù)達(dá)到'+this.number+'次啦')
},
add () {
this.number -= 1
}
}
})```
當(dāng)你點(diǎn)擊的時(shí)候執(zhí)行add方法,改變num的值,而watch正在監(jiān)聽(tīng)num的變化,此時(shí)當(dāng)num<5時(shí),即刻執(zhí)行alert方法,點(diǎn)擊次數(shù)到達(dá)了4次啦。
在我們需要依賴(lài)動(dòng)態(tài)的去改變data的值之后進(jìn)行邏輯其他邏輯操作的時(shí)候以及我們需要監(jiān)聽(tīng)數(shù)據(jù)結(jié)構(gòu)層次比較高的時(shí)候可以使用deep屬性進(jìn)行深度監(jiān)聽(tīng)。