computed和watch的區別
computed特性
1.是計算值,
2.應用:就是簡化tempalte里面{{}}計算和處理props或$emit的傳值,computed(數據聯動)。
3.具有緩存性,頁面重新渲染值不變化,計算屬性會立即返回之前的計算結果,而不必再次執行函數
watch特性
1.是觀察的動作,
2.應用:監聽props,$emit或本組件的值執行異步操作,watch(異步場景)。
3.無緩存性,頁面重新渲染時值不變化也會執行
注:watch:一般監聽單個變量或者一個數組或對象,computed: 監聽在同一個實例里的很多個變量。
watch 並不適用於顯示某一個數據以及數據的拼裝等。watch 用在監聽數據變化,做某些指令操作(給后台發數據請求)
一、computed
定義:是一個計算屬性,類似於過濾器,對綁定到view的數據進行處理
實現進行簡單的字符串拼接
1.不適用computed的用法
new Vue({ el: '#app', template:"<p>{{firstName +' '+ lastName}}</p>", data: { firstName: 'lucas', lastName: 'Root' }, }) /*lucas Root*/
2.使用computed
new Vue({ el: '#app', template:"<p>{{fullName}}</p>", data: { firstName: 'lucas', lastName: 'Root' }, computed:{ fullName(){ return `${this.firstName} ${this.lastName}`; } } })
3.使用methods方法
methods方法實現和computed相同拼接
let vm = new Vue({ el: '#app', template:` <div> <p>computed:{{fullName}}</p> <p>methods:{{names()}}</p> </div> `, data: { firstName: 'lucas', lastName: 'Root' }, computed:{ fullName(){ return `${this.firstName} ${this.lastName}`; } }, methods:{ names() { return `${this.firstName} ${this.lastName}`; } } }) /* computed:lucas Root methods:lucas Root */
注:computed屬性的fullName不可在data里定義,否則會報錯。
4.使用computed的好處
當我們改變data變量值時,整個應用會重新渲染,vue 會被數據重新渲染到 dom 中。這時,如果我們使用 names方法,隨着渲染,方法也會被調用,而 computed 不會重新進行計算,從而性能開銷比較小。當新的值需要大量計算才能得到,緩存的意義就非常大。
如果 computed 所依賴的數據發生改變時,計算屬性才會重新計算,並進行緩存;當改變其他數據時,computed 屬性 並不會重新計算,從而提升性能。
當我們拿到的值需要進行一定處理使用時,就可以使用 computed。
5.computed的get與set用法
let vm = new Vue({ el: '#app', template:` <div> <p>computed:{{fullName}}</p> </div> `, data: { firstName: 'lucas', lastName: 'Root' }, computed:{ fullName:{ /*若使用方法寫法fullName()會報錯,需使用屬性寫法*/ get() { //回調函數 當需要讀取當前屬性值是執行,根據相關數據計算並返回當前屬性的值 return `${this.firstName} ${this.lastName}`; }, set(val) { //監視當前屬性值的變化,當屬性值發生變化時執行,更新相關的屬性數據,val就是fullName的最新屬性值 const names = val.split(' '); console.log(names); this.firstName = names[0]; this.lastName = names[1]; } } }, }) vm.fullName="hello world"; //也可以在瀏覽器控制台修改輸出 /* computed:hello world */
二、watch
定義:watch是一個觀察的動作,例如,監聽 firstName 數據,並根據改變得到的新值,進行某些操作。
2.1示例
let vm = new Vue({ el: '#app', template:` <div> <p>computed:{{fullName}}</p> </div> `, data: { firstName: 'Lucas', lastName: 'Root', fullName:'names', }, watch:{ firstName (newName1,oldName1){ console.log('this firstName newName '+newName1); console.log('this firstName oldName '+oldName1); this.fullName = newName1 + ' ' + this.lastName; }, }, }) // vm.firstName="hello"; /* this firstName newName hello this firstName oldName Lucas */
上面是監聽firstName和lastName的變化,但是僅限簡單數據類型
注:watch:一般監聽單個變量或者一個數組,computed: 監聽在同一個實例里的很多個變量。
2.2監聽簡單數據類型
data(){ return{ 'first':2 } }, watch:{ first(){ console.log(this.first) } },
2.3 監聽復雜數據類型
1.深度監聽deep
不使用 deep 時,當我們改變 obj.a 的值時,watch不能監聽到數據變化,默認情況下,handler 只監聽屬性引用的變化,也就是只監聽了一層,但改對象內部的屬性是監聽不到的。
let vm = new Vue({ el:'#app', template: ` <div> <p>Obj.a: <input type="text" v-model="obj.a"/></p> </div> `, data: { obj: { a: '123' } }, watch: { obj: { handler () { console.log('obj.a changed') }, // immediate: true deep: true } } })
immerdiate 屬性:通過聲明 immediate 選項為 true,可以立即執行一次 handler。
通過使用 deep: true 進行深入觀察,這時,我們監聽 obj,會把 obj 下面的屬性層層遍歷,都加上監聽事件,這樣做,性能開銷也會變大,只要修改 obj 中任意屬性值,都會觸發 handler,那么如何優化性能呢?請看下面2.4監聽對象單個屬性
watch: { 'obj.a': { //監聽對象單個屬性a handler () { console.log('obj.a changed') }, immediate: true //該屬性會先執行一次handler // deep: true } }
2.4監聽對象單個屬性
方法一:可以直接對用對象.屬性的方法拿到屬性
let vm=new Vue({ el:'#app', template: ` <div> <p>Obj.Number: <input type="text" v-model="first.number"/></p> </div> `, data(){ return{ first:{ number:5, } } }, watch:{ 'first.number':function(newVal,oldVal){ //監聽單個屬性number console.log(newVal,oldVal); } }, })
