在vue的項(xiàng)目中攻冷,我們時(shí)常會(huì)需要對(duì)data的改變做出處理丈攒,這時(shí)候就需要用到watch和computed這兩個(gè)屬性,既然都是數(shù)值改變觸發(fā)改變的屬性狞甚,他們之間又有什么異同呢锁摔?筆者將在接下來(lái)進(jìn)行解析
computed:計(jì)算屬性
通過(guò)屬性計(jì)算而得來(lái)的屬性
1. get用法
data: {
firstName: 'Liu',
lastName: 'lu'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
fullName不可在data里面定義,因?yàn)閷?duì)應(yīng)的computed作為計(jì)算屬性定義fullName并返回對(duì)應(yīng)的結(jié)果給這個(gè)變量,變量不可被重復(fù)定義和賦值
2.get和set用法
data: {
firstName: 'Liu',
lastName: 'lu'
},
computed: {
fullName:{
get(){//回調(diào)函數(shù) 當(dāng)需要讀取當(dāng)前屬性值時(shí)執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計(jì)算并返回當(dāng)前屬性的值
return this.firstName + ' ' + this.lastName
},
set(val){//監(jiān)視當(dāng)前屬性值的變化入愧,當(dāng)屬性值發(fā)生變化時(shí)執(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];
}
}
}
注意:
1、computed內(nèi)部的函數(shù)名稱(chēng)可以隨意編寫(xiě)
2棺蛛、computed內(nèi)部的函數(shù)必須通過(guò)return的方式將結(jié)果進(jìn)行返回怔蚌,最好不要在內(nèi)部進(jìn)行賦值操作
3、雖然computed內(nèi)部是以函數(shù)的方式進(jìn)行編寫(xiě)旁赊,但是在調(diào)用的時(shí)候并不是一個(gè)函數(shù)桦踊,所以不需要加()
4、只要函數(shù)內(nèi)部所依賴(lài)的屬性發(fā)生了改變终畅,那么這個(gè)函數(shù)就會(huì)自己調(diào)用
5籍胯、如果函數(shù)內(nèi)部所依賴(lài)的屬性沒(méi)有發(fā)生改變的時(shí)候computed會(huì)從緩存中讀取結(jié)果
總結(jié):computed中的方法都是依賴(lài)于Vue中data里面的屬性,如果屬性發(fā)生了改變那么computed中所對(duì)應(yīng)的函數(shù)就會(huì)去執(zhí)行
使用的場(chǎng)景:當(dāng)多個(gè)屬性影響一個(gè)屬性的時(shí)候我們就需要用到computed离福,如下圖
watch:屬性監(jiān)聽(tīng)
作用:監(jiān)聽(tīng)data中屬性的變化 當(dāng)data中的屬性發(fā)生了改變后杖狼,那么watch中相對(duì)應(yīng)的函數(shù)就會(huì)執(zhí)行
1.示例
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
2.監(jiān)聽(tīng)簡(jiǎn)單數(shù)據(jù)類(lèi)型
data(){
return{
'first':2
}
},
watch:{
first(){
console.log(this.first)
}
}
3.監(jiān)聽(tīng)對(duì)象(數(shù)組)需用深度監(jiān)聽(tīng)
data(){
return{
'first':{
second:0
}
}
},
watch:{
secondChange:{
handler(oldVal,newVal){
console.log(oldVal)
console.log(newVal)
},
deep:true
}
}
console.log打印的結(jié)果,發(fā)現(xiàn)oldVal和newVal值是一樣的,說(shuō)明深度監(jiān)聽(tīng)雖然可以監(jiān)聽(tīng)到對(duì)象的變化,但是無(wú)法監(jiān)聽(tīng)到具體對(duì)象里面那個(gè)屬性的變化(地址沒(méi)有被改變,原先的數(shù)據(jù)被覆蓋)
注意事項(xiàng):
1妖爷、watch中的函數(shù)名稱(chēng)必須是所依賴(lài)data中的屬性名稱(chēng)
2蝶涩、watch中的函數(shù)是不需要調(diào)用的,只要函數(shù)所依賴(lài)的屬性發(fā)生了改變 那么相對(duì)應(yīng)的函數(shù)就會(huì)執(zhí)行
3、watch中的函數(shù)會(huì)有2個(gè)參數(shù) 一個(gè)是新值绿聘,一個(gè)是舊值
4嗽上、watch默認(rèn)情況下無(wú)法監(jiān)聽(tīng)對(duì)象的改變,如果需要進(jìn)行監(jiān)聽(tīng)則需要進(jìn)行深度監(jiān)聽(tīng) 深度監(jiān)聽(tīng)需要配置handler函數(shù)以及deep為true熄攘。(因?yàn)樗粫?huì)監(jiān)聽(tīng)對(duì)象的地址是否發(fā)生了改變兽愤,而值是不會(huì)監(jiān)聽(tīng)的)
5、watch默認(rèn)情況下第一次的時(shí)候不會(huì)去做監(jiān)聽(tīng)挪圾,如果需要在第一次加載的時(shí)候也需要去做監(jiān)聽(tīng)的話(huà)需要設(shè)置immediate:true
6浅萧、watch在特殊情況下是無(wú)法監(jiān)聽(tīng)到數(shù)組的變化
- 通過(guò)下標(biāo)來(lái)更改數(shù)組中的數(shù)據(jù)
- 通過(guò)length來(lái)改變數(shù)組的長(zhǎng)度
解決方案:
- 通過(guò)Vue實(shí)例方法set(object,key/index,value);
this.$set(this.arr,0,100);
- 通過(guò)splice來(lái)數(shù)組清空 $delete(object,key/index)
this.$delete(this.arr,0)
7、深度監(jiān)聽(tīng)對(duì)應(yīng)的函數(shù)名必須為handler,否則無(wú)效果,因?yàn)閣atcher里面對(duì)應(yīng)的是對(duì)handler的調(diào)用
總結(jié):
computed常用于值的計(jì)算哲思,如簡(jiǎn)化tempalte里面{{}}計(jì)算和處理props或$emit
的傳值惯殊,頁(yè)面重新渲染值不變化,計(jì)算屬性會(huì)立即返回之前的計(jì)算結(jié)果,而不必再次執(zhí)行函數(shù)也殖。
watch常用來(lái)觀察動(dòng)作,聽(tīng)props务热,$emit或本組件的值執(zhí)行異步操作,頁(yè)面重新渲染時(shí)值不變化也會(huì)執(zhí)行