【Vue】談Vue的依賴追蹤系統 ——搞懂methods watch和compute的區別和聯繫

 

從做用機制和性質上看待methods,watch和computed的關係

圖片標題[原創]:《他三個是啥子關係呢?》

 

 

首先要說,methods,watch和computed都是以函數爲基礎的,但各自卻都不一樣
 
而從做用機制和性質上看,methods和watch/computed不太同樣,因此我接下來的介紹主要有兩個對比:
1.methods和(watch/computed)的對比
2.watch和computed的對比

做用機制上

1.watch和computed都是以Vue的依賴追蹤機制爲基礎的,它們都試圖處理這樣一件事情:當某一個數據(稱它爲依賴數據)發生變化的時候,全部依賴這個數據的「相關」數據「自動」發生變化,也就是自動調用相關的函數去實現數據的變更。
2.對methods:methods裏面是用來定義函數的,很顯然,它須要手動調用才能執行而不像watch和computed那樣,「自動執行」預先定義的函數
 
【總結】:methods裏面定義的函數,是須要主動調用的,而和watch和computed相關的函數,會自動調用,完成咱們但願完成的做用
 

從性質上看

1.methods裏面定義的是函數你顯然須要像"fuc()"這樣去調用它(假設函數爲fuc)
2.computed計算屬性事實上和和data對象裏的數據屬性是同一類的(使用上),
例如:
computed:{
    fullName: function () { return  this.firstName + lastName }
}

 

你在取用的時候,用this.fullName去取用,就和取data同樣(不要當成函數調用!!)
3.watch:相似於監聽機制+事件機制
例如:
watch: {
   firstName: function (val) {  this.fullName = val + this.lastName }
}

 

firstName的改變是這個特殊「事件」被觸發的條件,而firstName對應的函數就至關於監聽到事件發生後執行的方法
 

watch和computed的對比

說了這麼多,下面先對watch和computed
 

 

首先它們都是以Vue的依賴追蹤機制爲基礎的,它們的共同點是:都是但願在依賴數據發生改變的時候,被依賴的數據根據預先定義好的函數,發生「自動」的變化
 
咱們固然能夠本身寫代碼完成這一切,但卻極可能形成寫法混亂,代碼冗餘的狀況。Vue爲咱們提供了這樣一個方便的接口,統一規則
 
但watch和computed也有明顯不一樣的地方:
watch和computed各自處理的數據關係場景不一樣
1.watch擅長處理的場景:一個數據影響多個數據
2.computed擅長處理的場景:一個數據受多個數據影響
 

watch擅長處理的場景:一個數據影響多個數據

 
 

 

(具體的看上圖就ok,這裏再也不贅述)
對於watch,咱們先從一個場景提及
 
在《海賊王》裏面,主角團隊的名稱叫作:「草帽海賊團」
因此咱們把船員依次稱爲:
草帽海賊團索隆,草帽海賊團娜美,以此類推。。。
咱們但願:當船團名稱發生變動的時候,這艘船上全部船員的名字一塊兒變動!!
例如:
有一天,船長路飛爲了增強團隊建設,弘揚海賊文化,決定「草帽海賊團」更名爲「橡膠海賊團」(路飛是橡膠惡魔果實能力者)
 
咱們代碼以下:
var vm = new Vue({
  el: '#app',
  /*
   data選項中的數據:
   1.haiZeiTuan_Name --> 海賊團名稱
   2.船員的名稱 = 海賊團名稱(草帽海賊團) + 船員名稱(例如索隆)
 
   這些數據裏存在這種關係:
   (多個)船員名稱數據 --> 依賴於 --> (1個)海賊團名稱數據
    一個數據變化 --->  多個數據所有變化
  */
  data: {
    haiZeiTuan_Name: '草帽海賊團',
    suoLong: '草帽海賊團索隆',
    naMei: '草帽海賊團娜美',
    xiangJiShi: '草帽海賊團香吉士'
  },
  /*
   在watch中,一旦haiZeiTuan_Name(海賊團名稱)發生改變
   data選項中的船員名稱所有會自動改變 (suoLong,naMei,xiangJiShi)
   並把它們打印出來
  */
  watch: {
    haiZeiTuan_Name: function (newName) {
      this.suoLong = newName + '索隆'
      this.naMei = newName + '娜美'
      this.xiangJiShi = newName + '香吉士'
      console.log(this.suoLong)
      console.log(this.naMei)
      console.log(this.xiangJiShi)
    }
  }
})
 
// 更改watch選項中監控的主數據
vm.haiZeiTuan_Name = '橡膠海賊團'

 

demo:
 

 

因而船員們的稱號前綴都被統一修改了!(本來是「草帽海賊團」)
 
 
可是咱們的路飛船長又突發奇想:我這麼喜歡吃肉,乾脆咱們叫作「肉肉海賊團」好了吧!
 

 

咱們把最下面的代碼改成:
// 更改watch選項中監控的主數據
vm.haiZeiTuan_Name = '肉肉海賊團'

demo:緩存

 

 

computed擅長處理的場景:一個數據受多個數據影響

 

咱們再從一個場景提及
 
路飛的全名叫作:蒙奇-D-路飛,他想成爲海賊王,但路飛的爺爺卡普(海軍英雄)所以感到很是惱怒,因而把「路飛」改爲了叫「海軍王」,但願他能改變志向
 
代碼以下:
var vm = new Vue({
  el: '#app',
  /*
   data選項中的數據:firstName,secName,thirdName
   computed監控的數據:lufei_Name
   二者關係: lufei_Name = firstName + secName + thirdName
   因此等式右邊三個數據任一改變,都會直接修改 lufei_Name
  */
  data: {
    // 路飛的全名:蒙奇·D·路飛
    firstName: '蒙奇',
    secName: 'D',
    thirdName: '路飛'
  },
  computed: {
    luFei_Name: function () {
      return this.firstName + this.secName + this.thirdName
    }
  }
})
 
// 將「路飛」改成「海軍王」
vm.thirdName = '海軍王'
// 打印路飛的全名
console.log(vm.luFei_Name)

 

demo:app

 可是:函數

有一天,路飛的逗逼爺爺卡普,一不當心發現可能把族譜搞錯了,實際上,他們不是「D」之一族,而是「H」一族,也就是說,「蒙奇-D-路飛」可能要叫作「蒙奇-H-路飛」了
 
將最後一段代碼改成以下:
// 將「D」改成「H」
vm.secName = 'H'
// 打印路飛的全名
console.log(vm.luFei_Name)

 

 
demo:
 

 

methods不處理數據邏輯關係,只提供可調用的函數

 
相比於watch/computed,methods不處理數據邏輯關係,只提供可調用的函數
new Vue({
  el: '#app',
  template: '<div id="app"><p>{{ say() }}</p></div>',
  methods: {
    say: function () {
      return '我要成爲海賊王'
    }
  }
})

 

 
 

從功能的互補上看待methods,watch和computed的關係

 

在不少時候,computed是用來處理你使用watch和methods的時候沒法處理,或者是處理起來並不太恰當的狀況的
 

利用computed處理methods存在的重複計算狀況

 

1.methods裏面的函數就是一羣「耿直Boy」,若是有其餘父函數調用它,它會每一次都「乖乖」地執行並返回結果,即便這些結果極可能是相同的,是不須要的
2.而computed是一個「心機Boy」,它會以Vue提供的依賴追蹤系統爲基礎,只要依賴數據沒有發生變化,computed就不會再度進行計算
 
例子:
new Vue({
  el: '#app',
  // 設置兩個button,點擊分別調用getMethodsDate,getComputedDate方法
  template: '<div id="app"><button @click="getMethodsDate">methods</button><button @click="getComputedDate">computed</button></div>',
  methods: {
    getMethodsDate: function () {
      alert(new Date())
    },
    // 返回computed選項中設置的計算屬性——computedDate
    getComputedDate: function () {
      alert(this.computedDate)
    }
  },
  computed: {
    computedDate: function () {
      return new Date()
    }
  }

 

第一次點擊methods按鈕:

 

第二次點擊methods按鈕:

 

 

注意兩次點擊methods返回的時間是不一樣的!!
 
第一次點擊computed按鈕:
 

 

第二次點擊computed按鈕:
注意兩次點擊computed返回的時間是相同的!!
1.兩次點擊methods返回的時間是不一樣的
2.注意兩次點擊computed返回的時間是相同的
 
【注意】爲何兩次點擊computed返回的時間是相同的呢?new Date()不是依賴型數據(不是放在data等對象下的實例數據),因此computed只提供了緩存的值,而沒有從新計算
 
只有符合:1.存在依賴型數據 2.依賴型數據發生改變這兩個條件,computed纔會從新計算。
 
而methods下的數據,是每次都會進行計算的
 

利用computed處理watch在特定狀況下代碼冗餘的現象,簡化代碼

 
 

 

new Vue({
  el: '#app',
  data: {
    fullName: '彭湖灣',
    firstName: '彭',
    secName: '湖',
    thirdName: '灣'
  },
  // watch中的代碼顯然是同類型,重複的,它並不簡潔,也不優雅
  watch: {
    firstName: function (newValue) {
      this.fullName = newValue + this.secName + this.thirdName
      console.log(this.fullName)
    },
    secName: function (newValue) {
      this.fullName = this.firstName + newValue + this.thirdName
      console.log(this.fullName)
    },
    thirdName: function (newValue) {
      this.fullName = this.firstName + this.secName + newValue
      console.log(this.fullName)
    }
  }
})

 

 
watch中的代碼顯然是同類型,重複的,它並不簡潔,也不優雅,因此咱們能夠把它變成這樣
new Vue({
  el: '#app',
  data: {
    fullName: '彭湖灣',
    firstName: '彭',
    secName: '湖',
    thirdName: '灣'
  },
  // 對watch中的代碼進行重構,實現一樣效果
  computed: function () {
    this.fullName = this.firstName + this.secName + this.thirdName
    console.log(this.fullName)
  }
})

 

相關文章
相關標籤/搜索