如何開發(fā)app小程序win優(yōu)化大師
目錄
前言
computed計算屬性
什么是計算屬性?
Vue的原有屬性是什么?
得到的全新的屬性是什么?
計算屬性怎么用?
計算屬性的作用是什么?
為什么說代碼執(zhí)行率高了?
computed計算屬性中的this指向
computed計算屬性簡寫
watch偵聽屬性
語法格式
watch偵聽屬性中的this指向
watch深度監(jiān)視
watch的簡寫
watch和computed如何選擇
異步情況下
computed
watch
watch中異步中箭頭函數(shù)和普通函數(shù)this指向
前言
繼上篇文章介紹了Vue配置項中的methods,本文繼續(xù)介紹Vue配置項中的computed計算屬性和watch偵聽屬性以及在使用如何選擇
computed計算屬性
什么是計算屬性?
使用Vue的原有屬性,經(jīng)過一系列的計算,最終得到了一個全新的屬性,叫做計算屬性。
Vue的原有屬性是什么?
data對象當中的屬性可以叫做Vue的原有屬性。
得到的全新的屬性是什么?
表示生成了一個新的屬性,和data中的屬性無關了,新的屬性也有自己的屬性名和屬性值。
計算屬性怎么用?
語法格式:需要一個新的配置項 computed
computed:{
? ? ? ? 計算屬性1:{
? ? ? ? ? ? ? ? get(){
? ? ? ? ? ? ? ? ? ? ? ? 當讀取計算屬性1時,getter方法被自動調用
????????????????},
? ? ? ? ? ? ? ? set(){
? ? ? ? ? ? ? ? ? ? ? ? 當修改計算屬性1時,setter方法被自動調用
????????????????}
????????},
? ? ? ? 計算屬性2:{}
}
計算屬性的作用是什么?
- 代碼得到了復用
- 代碼變得更加容易維護
- 代碼的執(zhí)行效率高了
為什么說代碼執(zhí)行率高了?
其實在methods中也可以調用函數(shù)方法來完成computed計算屬性能完成的事,那為什么會引入computed計算屬性呢?
舉例
<div class="app"><h1>{{msg}}</h1><input type="text" v-model="info">{{hh()}}{{hh()}}{{hh()}}{{hh()}}{{hh()}}{{xx}}{{xx}}{{xx}}{{xx}}{{xx}}</div><script>const vm = new Vue({el:'.app',data:{ msg:'computed計算屬性',info:''},methods:{hh(){console.log('methods方法執(zhí)行了');return 'hh'}},computed:{xx:{get(){console.log('計算屬性執(zhí)行了');return 'xx'}}}})</script>
執(zhí)行此代碼,methods中的函數(shù)方法以及computed中的計算屬性各調用5次
由結果看出,methods中的方法重復執(zhí)行了5次,而computed計算屬性只執(zhí)行了一次。
這是因為computed計算屬性遵循一個緩存機制,將重復存入瀏覽器中,使用時直接拿出來即可,這樣代碼的執(zhí)行效率就變高了
computed計算屬性中的this指向
methods中的this是指向vue實例的,那computed計算屬性中的this是指向什么呢?
<div class="app"><h1>{{msg}}</h1><input type="text" v-model="info">{{reverse}}</div><script>const vm = new Vue({el:'.app',data:{ msg:'computed計算屬性',info:''},computed:{reverse:{get(){console.log(this);}}}})</script>
可知,computed計算屬性中的this是指向Vue實例對象的
computed計算屬性簡寫
當不使用set()方法時,僅使用get()方法時可以使用簡寫
例:反轉字符串
<div class="app"><h1>{{msg}}</h1><input type="text" v-model="info">字符串反轉后 :{{reverse}}</div><script>const vm = new Vue({el:'.app',data:{ msg:'computed計算屬性',info:''},computed:{reverse(){return this.info.split('').reverse().join('')}}})</script>
直接省略get,將:換成()后接{}即可,簡寫和完整寫法對比
// 簡寫reverse(){return this.info.split('').reverse().join('')},// 完整寫法reverse:{get(){return this.info.split('').reverse().join('')}}
注意,簡寫后和methods中的函數(shù)方法寫法相同,但這不是函數(shù)方法,這是計算屬性
watch偵聽屬性
偵聽屬性變化
語法格式
watch:{//可以監(jiān)視多個屬性//監(jiān)視哪個屬性,直接寫屬性名字即可//可以監(jiān)視Vue的原有屬性,也可以監(jiān)視計算屬性num:{//固定寫法,方法名必須叫handler//當被監(jiān)視的屬性發(fā)生變化時,handler就會自動調用一次//handler方法有兩個參數(shù),前一個參數(shù)代表屬性值改變后的新值,后一個參數(shù)代表屬性值改變之前的舊值handler(newValue,oldValue){console.log(newValue,oldValue);}}}
watch偵聽屬性中的this指向
watch:{//可以監(jiān)視多個屬性//監(jiān)視哪個屬性,直接寫屬性名字即可//可以監(jiān)視Vue的原有屬性,也可以監(jiān)視計算屬性num:{//固定寫法,方法名必須叫handler//當被監(jiān)視的屬性發(fā)生變化時,handler就會自動調用一次//handler方法有兩個參數(shù),前一個參數(shù)代表屬性值改變后的新值,后一個參數(shù)代表屬性值改變之前的舊值handler(newValue,oldValue){console.log(this === vm);}}}
由此可知,watch中的this也是指向vue實例對象的
watch深度監(jiān)視
如何偵聽對象呢?
例:偵聽a對象里面的b
<div class="app"><h1>{{msg}}</h1><input type="text" v-model="a.b"></div><script>const vm = new Vue({el:'.app',data:{msg:'watch偵聽屬性',a:{b:0}},watch:{//可以監(jiān)視多個屬性//監(jiān)視哪個屬性,直接寫屬性名字即可//可以監(jiān)視Vue的原有屬性,也可以監(jiān)視計算屬性'a.b':{//固定寫法,方法名必須叫handler//當被監(jiān)視的屬性發(fā)生變化時,handler就會自動調用一次//handler方法有兩個參數(shù),前一個參數(shù)代表屬性值改變后的新值,后一個參數(shù)代表屬性值改變之前的舊值handler(newValue,oldValue){alert('111')}}}})</script>
偵聽這種嵌套的需要加上" ",原本就是有的,只是省略了,當偵聽這種嵌套關系時,需要加上" ".
如果更深層次的嵌套,是否需要一直“...”下去呢?
不需要,vue給我提供了deep屬性
deep:true(默認是false),當deep:true時,代表開啟了深度監(jiān)視,只需要監(jiān)視對象便可監(jiān)聽該對象內(nèi)的所有屬性
watch:{//可以監(jiān)視多個屬性//監(jiān)視哪個屬性,直接寫屬性名字即可//可以監(jiān)視Vue的原有屬性,也可以監(jiān)視計算屬性a:{deep:true,//固定寫法,方法名必須叫handler//當被監(jiān)視的屬性發(fā)生變化時,handler就會自動調用一次//handler方法有兩個參數(shù),前一個參數(shù)代表屬性值改變后的新值,后一個參數(shù)代表屬性值改變之前的舊值handler(newValue,oldValue){alert('111')}}}
watch的簡寫
原:
watch:{a:{handler(){console.log('監(jiān)聽到了');}}}
簡寫:
簡寫的條件是,不使用深度監(jiān)視及其他的任何屬性
watch:{a(){console.log('監(jiān)聽到了');}}
watch和computed如何選擇
- 當computed和watch都能完成某個功能時,優(yōu)先選擇computed
- 當程序中采用異步的方式時,只能使用watch
例:比較大小
先使用watch偵聽屬性
<div class="app"><h1>{{msg}}</h1><button @click="add1">+1</button><br><button @click="add2">+1</button><br>num1:{{num1}}<br>num2:{{num2}}<br>比較結果:{{daxiao}}</div>
<script>const vm = new Vue({el:'.app',data:{msg:'computed和watch的選擇',num1:1,num2:1,daxiao:""},methods:{add1(){return this.num1++},add2(){return this.num2++}},watch:{num1(){if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},num2(){if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},}})</script>
可以完成該功能
使用computed計算屬性
<script>const vm = new Vue({el:'.app',data:{msg:'computed和watch的選擇',num1:1,num2:1,daxiao:""},methods:{add1(){return this.num1++},add2(){return this.num2++}},computed:{daxiao(){if(this.num1 == this.num2){return this.num1 +'='+ this.num2}else if(this.num1 > this.num2){return this.num1+'>'+ this.num2}else {return this.num1+'<'+this.num2}}},})</script>
也能完成該功能,此種情況下選擇computed計算屬性
異步情況下
computed
computed:{daxiao(){setTimeout(()=>{if(this.num1 == this.num2){return this.num1 +'='+ this.num2}else if(this.num1 > this.num2){return this.num1+'>'+ this.num2}else {return this.num1+'<'+this.num2}},3000)}},
無法完成比較大小的功能
這是因為,在異步情況下的箭頭函數(shù)由誰調用,this就指向誰,這里的是由javascript引擎調用的,return的時候也是把值返回給javascript引擎
watch
watch:{num1(){setTimeout(()=>{if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},2000)},num2(){setTimeout(()=>{if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},2000)},}
在異步情況下,watch可以完成該功能
watch中異步中箭頭函數(shù)和普通函數(shù)this指向
分別在箭頭函數(shù)以及普通函數(shù)中打印this
watch:{num1(){setTimeout(()=>{console.log(this);if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},2000)},num2(){setTimeout(function(){console.log(this);if(this.num1 == this.num2){this.daxiao= this.num1 +'='+ this.num2}else if(this.num1 > this.num2){this.daxiao= this.num1+'>'+ this.num2}else {this.daxiao= this.num1+'<'+this.num2}},2000)},}
可以看出,在箭頭函數(shù)中,this是指向Vue實例的,反而普通函數(shù)中的this指向window
在箭頭函數(shù)中,this之所以指向Vue實例是因為,箭頭函數(shù)是沒有this,是繼承過來的,那么在異步中,該函數(shù)是被Vue實例管理的num1調用的,所以this是指向Vue實例的
在普通函數(shù)中,this指向調用者,settimeout異步是window調用的,所以this是指向window的