computed 的簡單任務--只讀不寫

甚麼是 Computed

在 Vue 中有一個叫 computed 的神奇方法,它可以觀察在data的變數,一旦變數有了改變,就會去取變數來運算,產生一個新的值呈現在畫面上,而這個新的值不會寫回 Option API 的 data 中。

先來個簡單的計算,看看它神奇的地方:
Computed 去觀察 numprice 這兩個資料,一但數值有變化,就算一個新的數值到畫面上。
HTML 這樣寫:

<div id="app">
  <h3>計算機</h3>
  <div>
    數量: {{num}} <br>
    <input type="text" v-model.num="num">
  </div>
  <div>
    價格: {{price}} <br>
    <input type="text" v-model.num="price">
  </div>
  <!--  {{}} 需要與 computed 內的函式同名  -->
  總價(表達式 num * price ) : {{ total }} <br>
</div>

JavaScript 這樣寫:

const app = {
  data() {
    return {
      message:'',
      num:0,
      price:100
    }
  },
  computed:{
    //函式需與在 HTML 中的觀察對象 {{}} 相同名稱
    total(){
    //可以同時觀察多個對象,在這裡同時觀察 num 與 price
      return this.num * this.price
    }
  }
}
Vue.createApp(app).mount('#app')

Computed 的特性:

  • 在大部分情境中(Getter),只讀不寫,一旦在 data 中,Computed 所觀察的對象有變化,就會進行運算,然後產生一個值渲染到畫面上,而這個新的值並不會寫回 data
  • 可以同時監聽多個變數,只要其中一個改變,就會重新運算。
  • 沒有被 Computed 監聽的變數不會觸發 computed。
  • computed 是一個物件。

Computed 和 利用兩對大括號渲染運算結果 的比較

當然也可以在 HTML 中加入 {{ 對應的資料名稱 }} ,就可以讓畫面與資料連動,只是如果相同的資料要運用在多個地方就要反覆去寫相同的{{運算式}}

HTML 這樣寫:

<div id="app">
  <h3>計算機</h3> 
  <div>    
  數量: {{num}} <br>  
  <input type="text" v-model.num="num1"> 
  </div>
   <div>    
  價格: {{price}} <br>  
  <input type="text" v-model.num="price"> 
  </div>
<!--  {{}} 中可以放入表達式  -->
  總價(表達式 num1 * price ) {{ num * price }} <br>
</div>

JavaScript 這樣寫:

const app = {
  data() {
    return {
      num:0,
      price:0
    }
  }  
}
Vue.createApp(app).mount('#app')

在 methods 中使用函式運算

如果要重複運算相同的資料,methods 也可以做到,我們可以在 methods 中使用函式,將運算的過程封裝進去。

在 HTML 中只要寫 {{ 函式名稱() }} 就可以了,methods 中的函式會去修改資料與同時將運算結果呈現在 HTML 中的 {{ 函式名稱() }} 的位置。

在這裡承前題,但是加入一個折扣的<input>輸入框,也在資料中新增一個 discount 的屬性,計算處理上也加上「乘以折扣」的程序。

<div id="app">
  <h3>計算機</h3> 
  <div>    
  數量: {{num}} <br>  
  <input type="text" v-model.num="num"> 
  </div>
   <div>    
  價格: {{price}} <br>  
  <input type="text" v-model.num="price"> 
  </div>
  <div>    
  折扣: {{discount}} %<br>  
  <input type="text" v-model.num="discount"> 
  </div>
<!--  {{}} 中可以放入表達式  -->
  總價(表達式 num1 * price ) {{ num * price * discount/100 }} <br>
  總價( methods ) {{totalMethod()}}  
</div>
</div>
const app = {
  data() {
    return {
      discount:100,
      num:0,
      price:0
    }
  },
  methods:{
    totalMethod(){
      console.log('methods')
      return this.num * this.price*this.discount/100;
    }
  }
}
Vue.createApp(app).mount('#app')

Methods 是急驚風,Computed 是慢郎中

承上題,我們加入一個不相干的 message 屬性,與畫面上 message 輸入框連動:

<div id="app">
  <h3>計算機</h3> 
  message: <br>
  <input type="text" v-model="message">
  <div>    
  數量: {{num}} <br>  
  <input type="text" v-model.num="num"> 
  </div>
   <div>    
  價格: {{price}} <br>  
  <input type="text" v-model.num="price"> 
  </div>
<!--  {{}} 中可以放入表達式  -->
  總價(表達式 num1 * price ) {{ num * price }} <br>
<!-- methods 中的函式   -->
  總價( methods ) {{totalMethod()}} 
  總價( computed ) {{totalComputed}} 
</div>
const app = {
  data() {
    return {
      message:'',
      num:0,
      price:0
    }
  },
  methods:{
    totalMethod(){
      console.log('methods')
      return this.num * this.price;
    }
  },
  computed:{
    totalComputed(){
      console.log('computed')
      return this.num * this.price;
    }
  }
}
Vue.createApp(app).mount('#app')

當我們改變 this.numthis.price 會同時觸發 console.log('methods')console.log('computed'),但是我們會發現在 message 輸入框中更新 data 的時候,
console.log('methods') 也會被觸發,但是 console.log('computed') 卻沒有反應,這是因為 this.message 不是 totalComputed() 的觀察對象。

而 methods 只要 data 中的資料有任何風吹草動,他都會觸發。

我們可以說 Methods 是急驚風,而 Computed 則是天塌下來,只要我家沒事,都不理會。

computed 與 methods 的差別:

  • computed 只有在自己觀察的值有變動時才會觸發,而 methods 則是所有的資料有變動時都會觸發。
  • computed 運作的結果只會呈現在畫面中,不會寫回資料(data),除非有加上 setter(),才會改變資料的內容。

computed 的簡單任務--只讀不寫
https://popeye-ux.github.io/2023/01/14/vue-computed-1/
作者
POPEYE
發布於
2023年1月14日
許可協議