computed 的簡單任務--只讀不寫
甚麼是 Computed
在 Vue 中有一個叫 computed
的神奇方法,它可以觀察在data
的變數,一旦變數有了改變,就會去取變數來運算,產生一個新的值呈現在畫面上,而這個新的值不會寫回 Option API 的 data
中。
先來個簡單的計算,看看它神奇的地方:
Computed 去觀察 num
跟 price
這兩個資料,一但數值有變化,就算一個新的數值到畫面上。
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.num
與 this.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(),才會改變資料的內容。