--- tags: Javascript, Vue --- # Vue watch和computed筆記 ## watch 1. 監聽"單一"變數觸發事件 1. 該函式可同時操作多個變數操作 ### 監聽單一元素 監聽當`text`改變,觸發函式,`watch`的`callback`函式會有新值跟舊值傳入 ```javascript= new Vue({ // ... data: { // ... text: '', }, watch: { // ... text(new, old) { console.log(`文字改變,從${old}變成${new}`); } } }); ``` ### Deep Watchers深度觀察 當要監聽一個物件的時候可以使用此方法,`newValue`以及`oldValue`會返回一個物件 ```javascript= 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`創建觀察者 觀察一個屬性名稱: ```javascript= this.$watch('a', (newVal, oldVal) => {}) ``` 使用$watch()實例方法強制創建觀察者: ```javascript= export default { created() { this.$watch('question', (newQuestion) => { // ... }) } } ``` ## computed 1. 監聽多個變數觸發事件 1. 會產生一個值 如果有需要複雜計算的屬性,會建議放在`computed`裡面,`computed`預設是`getter-only`,就是只能取得值但不能做修改,來看以下範例 原先我們要在模板內使用以下程式碼做運算,但如果過多邏輯在模板內,會變得難維護 ```vue= <p>{{ `是否擁有商品: ${this.author.products.length > 0 ? 'Yes' : 'No'}` }}</p> export default { data() { return { author: { products: [ '電腦', '滑鼠', '鍵盤' ] } } } } ``` 我們可以在`computed`加上`publishedproductssMessage`,然後改變模板寫法,以下結果就跟上述範例是一樣的。 ```vue= <p>{{ `是否擁有商品: ${ publishedproductssMessage }` }}</p> export default { data() { return { author: { products: [ '電腦', '滑鼠', '鍵盤' ] } } }, computed: { // a computed getter publishedproductssMessage() { return this.author.products.length > 0 ? 'Yes' : 'No' } } } ``` `computed`函式內的值有改變,才會更動,如果沒有更動他就跟`methods`一樣,比如取得時間。 ```vue= computed: { getTime() { return new Date().toLocaleTimeString(); }, } ``` 預設情況下`computed`是不能寫入值,可以透過`getter` 和 `setter`來把值寫回`data`,查看範例。 當`fullName`裡面的資料被更新時,才會觸發`fullName`的`getter`,順序為`getter->updated`,當我們要進行設值時,就將程式碼寫在`setter`中,點擊按鈕設值,執行順序為`setter->getter->updated` ,但要注意`setter`不一定會觸發`getter`除非有更改到`getter`裡面的值。 ![](https://i.imgur.com/kmCtluE.gif) ```vue= <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(" "); }, }, }, } ```