Vue watch 和 computed 筆記

watch

  1. 監聽”單一”變數觸發事件
  2. 該函式可同時操作多個變數操作

監聽單一元素

監聽當text改變,觸發函式,watchcallback函式會有新值跟舊值傳入

new Vue({
// ...
data: {
// ...
text: '',
},
watch: {
// ...
text(new, old) {
console.log(`文字改變,從${old}變成${new}`);
}
}
});

Deep Watchers 深度觀察

當要監聽一個物件的時候可以使用此方法,newValue以及oldValue會返回一個物件

new Vue({
// ...
data: {
// ...
product: {
name: "電腦",
price: 100,
},
},
watch: {
product: {
handler(newValue, oldValue) {
console.log(`更改後${newValue},更改前${oldValue}`);
// Note: `newValue` will be equal to `oldValue` here
// on nested mutations as long as the object itself
// hasn't been replaced.
},
deep: true,
},
},
});

強制創建watch實例

可以使用$watch創建觀察者

觀察一個屬性名稱:

this.$watch("a", (newVal, oldVal) => {});

使用$watch()實例方法強制創建觀察者:

export default {
created() {
this.$watch("question", (newQuestion) => {
// ...
});
},
};

computed

  1. 監聽多個變數觸發事件
  2. 會產生一個值

如果有需要複雜計算的屬性,會建議放在computed裡面,computed預設是getter-only,就是只能取得值但不能做修改,來看以下範例

原先我們要在模板內使用以下程式碼做運算,但如果過多邏輯在模板內,會變得難維護

<p>{{ `是否擁有商品: ${this.author.products.length > 0 ? 'Yes' : 'No'}` }}</p>

export default {
data() {
return {
author: {
products: [
'電腦',
'滑鼠',
'鍵盤'
]
}
}
}
}

我們可以在computed加上publishedproductssMessage,然後改變模板寫法,以下結果就跟上述範例是一樣的。

<p>{{ `是否擁有商品: ${ publishedproductssMessage }` }}</p>

export default {
data() {
return {
author: {
products: [
'電腦',
'滑鼠',
'鍵盤'
]
}
}
},
computed: {
// a computed getter
publishedproductssMessage() {
return this.author.products.length > 0 ? 'Yes' : 'No'
}
}
}

computed函式內的值有改變,才會更動,如果沒有更動他就跟methods一樣,比如取得時間。

computed: {
getTime() {
return new Date().toLocaleTimeString();
},
}

預設情況下computed是不能寫入值,可以透過gettersetter來把值寫回data,查看範例。

fullName裡面的資料被更新時,才會觸發fullNamegetter,順序為getter->updated,當我們要進行設值時,就將程式碼寫在setter中,點擊按鈕設值,執行順序為setter->getter->updated
,但要注意setter不一定會觸發getter除非有更改到getter裡面的值。

<div>
<p>firstName: {{ firstName }}</p>
<p>lastName: {{ lastName }}</p>
<p>fullName: {{ fullName }}</p>
<input type="text" v-model="inputName" />
<button @click="fullName=inputName">更新</button>
</div>
export default {
data() {
return {
firstName: "Joe",
lastName: "Wang",
inputName: "",
};
computed: {
fullName: {
// getter
get() {
return this.firstName + " " + this.lastName;
},
// setter
set(newValue) {
[this.firstName, this.lastName] = newValue.split(" ");
},
},
},
}