此篇後面會有點難懂,可以去看我的範例,更了解實際運作喔,各位加油!
computed 計算屬性
computed
大部分都是讀取data
資料經過運算後,在渲染到畫面上:
使用computed
的好處是能讓模板看起來簡潔:
<div id='app'>
<div>{{ one + two + three }}</div> //未使用computed
<div>{{ run }}</div> //使用computed
</div>
const vm = Vue.createApp({
data() {
return {
one: 1,
two: 2,
three: 3
};
},
computed: {
run() {
return this.one + this.two + this.three;
}
}
});
vm.mount("#app");
{{ one + two + three }} 可以改成{{ run }},如果是使用methods
就要改成{{ run() }}
,另外使用computed
時開頭一定要加上return
。
computed
與 methods
的差異?
<div id='app'>
<div>
<p>methods: {{ num() }}</p>
<p>methods: {{ num() }}</p>
<p>methods: {{ num() }}</p>
<p>computes: {{ run }}</p>
<p>computes: {{ run }}</p>
<p>computes: {{ run }}</p>
</div>
</div>
const vm = Vue.createApp({
data() {
return {
count: 0,
four: 4,
}
},
methods: {
num() {
console.log('isMethods');
return this.four + this.count;
}
},
computed: {
run() {
console.log('isComputed');
return this.four + this.count;
}
}
});
vm.mount('#app')
console.log:
模板區塊一樣是各三個,run
只有執行一次,而num()
卻執行了三次,這是因為computed
的特性,computed
會將計算過的結果暫存起來,computed
的更新條件是原始資料有變更才會更新。
如果有需要計算大量的功能,如果沒有使用computed
,每次調用將會消耗大量資源來計算,如果不需要暫存則改用methods
代替。
另外computed
裡的function
無法使用參數。
computed
常用技巧<div id='app'>
<input type="search" v-model="search">
<ul>
<li v-for="item in filter">
{{ item.name }}-{{ item.price }}
</li>
</ul>
</div>
const vm = Vue.createApp({
data() {
return {
search: '',
products: [
{
name: '上衣',
price: 500,
},
{
name: '褲子',
price: 700,
},
{
name: '鞋子',
price: 2000,
},
{
name: '襪子',
price: 450,
},
],
}
},
computed:{
filter() {
return this.products.filter(item => {
return item.name.match(this.search);
});
},
}
}).mount('#app')
input
輸入框輸入任何字串都會執行迴圈,文字如果部分相符,就會顯示出來:filter
將每一筆調用出來。match()
當item.name的字串有符合input輸入的文字就調用出來。
getter
與setter
getter
:將data
資料取出
到computed
運算完之後渲染到畫面。setter
:把資料(以下範例使用methods
)運算完,傳回data
。
首先computed
裡面要改成物件形式(total
),在物件裡面新增get()
的函式:
<div id="app">
<ul>
<li v-for="product in products">
{{ product.name }} / {{ product.price }}
<button type="button" @click="addToCart(product)">+</button>
</li>
</ul>
<h3>total 的值:{{ total }}</h3>
<h3>Computed Getter, Setter</h3>
computed sum 的值:
<input type="number" v-model.number="num">
<button type="button" @click="total = num">更新</button>
total 的值:{{ total }}<br>
computed sum 的值::{{ sum }}
</div>
const App = {
data() {
return {
products: [
{
name: '上衣',
price: 300,
},
{
name: '褲子',
price: 500,
},
{
name: '鞋子',
price: 1500,
},
{
name: '帽子',
price: 600,
},
],
carts: [],
sum: 0,
num: 20,
}
},
computed: {
total: {
get() {
let total = 0;
this.carts.forEach(item => {
total += item.price;
});
return total;
}
},
},
methods: {
addToCart(product) {
this.carts.push(product);
},
}
};
Vue.createApp(App).mount('#app');
input v-model.number="num"已經綁定data的num
,預期是點擊更新(@click="total=num")
會將total的值變成num
:
[Vue warn]: Write operation failed: computed property "total" is readonly。此值只能被讀取。
這時就要使用set()函式
,將他加入到computed
裡面的total物件
:
computed: {
total: {
get() {
let total = 0;
this.carts.forEach(item => {
total += item.price;
});
return this.sum || total;
// 如果 this.sum 有值就回傳,沒有值就使用 total 的值。
},
set(val) {
console.log('val') // num 的20
this.sum = val; // num 的20,傳回 data 的 sum
}
},
},
CodePen[完整範例]
整個流程:
1.get()
會先執行一次,computed
會先自己計算一次並暫存。
2.點擊帽子+把金額帶到total,再次觸發get(),total的值變成600。
2.點擊更新觸發set(val)函式,數字20傳回this.sum,同時{{ sum }} 變成 20。
3.最後再次觸發get()把total的值也變成 20。
可以打開CodePen
觀察console.log
的變化,可以發現getter
和setter
是分開進行的。
如上述有任何錯誤,歡迎指教,感謝你的收看,明天見。