[ Vue筆記 ] 計算屬性 computed 的使用


Posted by Akira on 2022-01-12

computed 的由來

computed的設計是為了不在模板中放入太多的運算。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

每個值的運算方式都要這樣寫的話,會讓版面的可讀性降低。

computed 的使用方式

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    reversedMessage: function () {
      console.log('computed reversedMessage')
      return this.message.split('').reverse().join('')
    }
  }
})

我們可以看到結果:
Original message: "Hello"
Computed reversed message: "olleH"

computeddata屬性一樣能把值取出來放在樣板上使用。computed在偵測到與之相關聯的原始資料有修改後,就會執行一次。

computed 特性

  • 在生命週期 created 時,computed 會被建立和執行一次,之後如果與之相關聯的原始資料沒有更新,就不會重新求值,而是回傳暫存的值。
  • computed 無法被其他方法修改。
  • computed 必須回傳一個值( 要用 return )。
  • computed 無法傳入參數。

computed 和 methods 差別

  • computed只有在與之相關聯的原始資料發生改變時,才會重新求值。而method在任一資料發生改變、或是被呼叫時便會執行。
  • method可傳入參數,且不一定要回傳一個值。
<div id="example">
  <p>Irrelevant data: "{{ otherMessage }}"
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ computedReversedMsg }}"</p>
  <p>Method reversed message: "{{ methodReversedMsg() }}"</p>
</div>
new Vue({
  el: '#example',
  data: {
    message: 'Hello',
    otherMessage: 'Hi'
  },
  computed: {
    computedReversedMsg() {
      console.log('computed reversedMessage')
      return this.message.split('').reverse().join('')
    }
  },
  methods:{
     methodReversedMsg() {
      console.log('method reversedMessage')
      return this.message.split('').reverse().join('')
    }
  }
})

假設data裡有兩個資料,一個和 computed 、 methods 都沒關係的otherMessage,一個是會影響 computed 和 methods 的message

當我更改了otherMessage時,因為沒有觸發 computed 內的原始資料,所以 computed 不會執行。但 methods 內卻因有資料變動,而執行了一遍。

computed 和 watch 差別

  • watch 只會偵測單一值,當該值有變化時,就會執行。
  • watch 可傳入參數,第一個參數是更新後的值,第二是舊值。
  • watch 可以處理非同步工作。
<div id="example">
  <p>firstName: "{{ firstName }}"</p>
  <p>lastName: "{{ lastName }}"</p>
  <p>fullName: "{{ fullName }}"</p>
</div>
new Vue({
  el: '#example',
  data: {
    firstName: 'Chloe',
    lastName: 'Lin',
    fullName: 'Chloe Lin'
  },
  watch:{
    firstName: function (val) {
      console.log('watch firstName')
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      console.log('watch lastName')
      this.fullName = this.firstName + ' ' + val
    }
  }
})

更改 firstName 時,由於 watch 監聽 firstName ,因此執行函式,進而修改 fullName 。

這種情況,使用 computed 看起來更簡潔,且有暫存資料,效能會比較好。

<div id="example">
  <p>firstName: "{{ firstName }}"</p>
  <p>lastName: "{{ lastName }}"</p>
  <p>fullName: "{{ fullName }}"</p>
</div>
new Vue({
  el: '#example',
  data: {
    firstName: 'Chloe',
    lastName: 'Lin',
  },
  computed: {
    fullName(){
      return this.firstName + ' ' + this.lastName
    }
  }
})

getter 與 setter

一般情況下,computed只會調用 getter 。但在某些情況下你可以根據你的需求使用 setter 。例如在input中,computed的資料綁定 v-model 。 input 中的值會以參數 newValue 傳進 computed 中的 setter 作處理,再拋給 getter ,最後輸出畫面。

<div id="example">
  <input type="text" name="name" v-model="fullName">
  <label for="">{{ fullName }}</label>
  <p>firstName: {{ firstName }}</p>
  <p>lastName: {{ lastName }}</p>
</div>
new Vue({
  el: '#example',
  data: {
    firstName: 'Chloe',
    lastName: 'Lin'
  },
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
},
})

參考資料
那些關於 Vue 的小細節 - Computed 中 getter 和 setter 觸發的時間點
不只懂 Vue 語法:試解釋 computed、watch 與 methods 的差異?
Computed Properties and Watchers


#Vue.js #Vue #Web #frondend







Related Posts

記一次 Leetcode 刷題體悟 - Valid Number

記一次 Leetcode 刷題體悟 - Valid Number

給 TensorFlow 初學者或害怕複雜 API 的人的學習建議

給 TensorFlow 初學者或害怕複雜 API 的人的學習建議

JavaScript 的判斷式

JavaScript 的判斷式


Comments