Vue核心知識——computed和watch的細節全面分析


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);
          }
        },
    })

vm.$watch的深度監聽

 

部分資料來源

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM