【Day02】 計算屬性, 監聽器 & 事件處理


前言

Day02 主要複習計算屬性(computed)、監聽器(watch)和事件處理(methods)。
對於他們的認識:methods還好不難理解;計算屬性和監聽器我比較沒弄懂(゚д⊙)
今天將這三個擺在一起做個了結比較,觀察他們之間不同處,
搞懂每個的使用時機及用法。


計算屬性

computed

模板裡也可以寫JS的表達式,像是:

<div id="app">
  {{ msg.split('').reverse().join('') }}
</div>

但表達式太長會讓人頭痛不好讀,未來也難維護。😥
這時候就可以用計算屬性-computed了!

computed屬性隨著來源data變化而更動。它可以讀取(getter)和設值(setter
在預設情況下是只有getter而已。


getter

computed試試看獲取名字

var vm = new Vue({
    el: '#app',
    data: {
        firstName: 'chihuahua',
        lastName: 'warrior',
    },
    computed: {
        fullName(){
            return `${this.firstName} ${this.lastName}`
        }
    }
})
<div id="app">
    {{ fullName }}
</div>


💡 computed預設是用getter,所以可省略getter不寫。

⚠️ 如果在模板中未使用{{fullName}},如有更動firstName或lastName的值computed雖然會更新但不會呈現結果!


setter

把上面的例子再修改一下,setter到底是什麼呢?

<div id="app">
    firstName <input type="text" v-model="firstName">
    <p/> lastName <input type="text" v-model="lastName">
    <p/> fullName <input type="text" v-model="fullName">
</div>
computed: {
    fullName: {
        // getter
        get() {
            console.log('getter')
            return `${this.firstName}  ${this.lastName}`
        },

        // setter
        set(newVal) {
            console.log('setter', newVal)
        }
    }
}


▲ 修改firstName或lastName的值,會觸發getter,進而更改fullName;
直接更動fullName,會觸發setter,使得firstName或lastName的值也會跟著變化!

💡 我覺得可以這樣理解:

  • getter:獲取值(且會緩存),computed的值是怎麼來的。
  • setter:設置值,給computed賦值,參數就是接收的值。

監聽器

watch

剛學的時候,覺得computed就做得到的工作,為何還需要watch
而且看起來沒什麼差別啊,有種既生瑜何生亮的概念
等學到比較多東西之後回頭看,才發現自己錯得超大啊QQ!!

watch:是一個物件,其屬性是需要觀察的表達式,值是對應回調函數。
值也可以是方法名或者包含選項的物件。
當資料發生變化時,執行非同步開銷較大的動作時會執行的函數。

把上面computed的例子改寫成watch看看

watch: {
    firstName(val) {
      this.fullName = `val ${this.lastName}`
    },
    lastName(val) {
      this.fullName = `${this.firstName} val`
    }

我要一個fullName需要把firstName和lastName的值都做觀察,
如果今天資料很大我會眼睛痛rrrrrr!
這時用computed可以比較快完成和易讀。

非同步watch可以參考官方的例子
才不是因為太懶有現成的才不寫例子(◔౪◔)


$watch

剛走一個watch,又來一個$watch!這兩個又有什麼差別?
Vue實例將會在實例化時調用$watch(),遍歷watch物件的每一個屬性。


▲ 翻譯翻譯,什麼是$watch啊!! 圖源網易

$watch 是註冊監聽器的函數
watch 是為了開發者方便在實體上設置監聽器而提供的
其實 watch 本身也是使用 $watch註冊監聽器。

📢 上文引用自Peter Chen大大的勇者鬥Vue龍

我覺得這個說法很容易理解watch$watch的關係!

詳細用法像是deepimmediate可以看官方的API文件


事件處理

監聽事件

可以用v-on指令監聽DOM事件,在觸發時運行JavaScript程式。

<div id="app">
    <span>覺得吉娃娃可愛的人有 {{ count }} 人</span>
    <button @click="count += 1"> +1 </button>
</div>
var vm = new Vue({
        el: '#app',
        data: {
            count: 999,
        },
    })


▲ 按下之後執行count+=1


事件方法

如果程式碼太長太複雜,都寫在v-on裡是不可行的!
所以就有了methods幫助我們解決這個問題。

把上面的東西修改一些,再包到methods裡面:

⚠️ methods中多個function都要用逗點(,)隔開,不然會報錯喔!

<button @click="sub" class="btn btn-danger"> -1 </button>
<span>覺得吉娃娃可愛的人有 {{ count }} 人</span>
<button @click="add" class="btn btn-info"> +1 </button>
data: {
    count: 0,
},

methods: {
    sub(){
        // 如果小於0就return,為了讓人數不為負
        if (this.count <= 0) return; 
        this.count--;
        },

    add(){
        this.count++;
        }
    }


▲ 出來的結果是這樣子~樣式部分用bootstrap快速又美觀(?) 可惜不能用Vuetify


🤔 如果不是要傳參數進去,在v-on調用方法的地方加括號會怎麼樣呢?

<button @click="question"> question </button>
<button @click="question()"> question() </button>
methods: {
    question() {
        console.log(this, arguments);
        }
    }


所有在methods屬性中的函數,無論如何調用,this都指向當前Vue實例化
要在事件響應函數中獲得event,那麼事件綁定時不能加括號。
當然也可以使用Vue的$event來顯示的傳遞event,以保證function寫在任何位置都可以正常使用thisevent


有點重要的補充⭐⭐⭐

computed vs. watch vs. methods

作用

  1. computedwatch:都是當某一個依賴資料發生變化時,自動調用相關函數去實現資料的變動。
  2. methodsmethods是用來定義函數的,它需要調用才能執行。

區分

  1. computed:一個資料多個資料影響。
    (例如上面例子fullName是由firstName和lastName組成)
  2. watch:一個資料影響多個資料。
  3. methods:不處理資料邏輯關係,只提供可調用的函數。

💣地雷誤區要小心💣

一開始也因為有些觀念不太清楚而踩雷。
找了很多資料複習,發現很多是原生JS的觀念!
尤其是ES6,雖然讓撰寫起來超~方~便~但有些地方真的...⚡⚡
深感學一個框架最重要的是基本底子要好,學Vue的話必備ES6知識。
地基都打不穩了蓋什麼房子不倒才怪484


缺 "this" 不可

看到上面事件方法中的例子,如果我們在sub / add函數中直接寫 count-- / count++,
不加this的結果會發生什麼事呢?


▲ 奇怪ㄟ怎麼不會動! :(

為什麼會這樣?如果不懂this一定要先搞懂!

📢 讀this必看this!閱讀Kuro大大的 What is This in JavaScript

搞懂this了嗎?再來看為什麼會這樣呢~
Vue的實例創建時是new出來的,所以this指向這個Vue實例
要使用Vue裡data的資料就是用this.count囉!


箭頭函數的地雷

ES6推出的箭頭函數可以把function簡化不少,但是在Vue要小心使用。
來試試寫一個按鈕,按了會console出現Hello 參數的函式:

<button @click="greeting('hello!')"> say HI! </button>

原本一般的function是這樣的

methods: {
    greeting: function(msg){
        console.log(`Hello ${this.msg}`)
    }
}

用箭頭函數把他簡化成醬子

methods: {
    greeting(msg) => {
        console.log(`Hello ${this.msg}`)
    }
}


▲ 為什麼是Hello undefined?

嗯?不在實例中,那麼這個this.msg到底跑哪去了?
我們在Vue的外部(也就是var vm = new Vue({ ... })外面)定義宣告msg:

var msg = "out side msg"


由此可知,在Vue中使用箭頭函數是不可靠的:(

💡 箭頭函數它沒有自己的 this,它綁定到其定義時所在的物件,而不是使用時所在的物件。
所以this不會指向Vue實例。


小小心得

若觀念或內容有誤請不吝指教,謝謝您( ᐛ)パァ

今天複習了我區分不太出來的computed和watch,
發現了以前真的很混啊啊啊啊都沒認真(๑•́ ₃ •̀๑)
現在才發現這些其實不難,用心整理、實際體會過一次就知道了。

還剩5天,加油!(๑•̀ㅂ•́)و✧


📢參考文章

#javascript #Vue #Web #前端







你可能感興趣的文章

金魚系列、定位篇

金魚系列、定位篇

容器化的概念

容器化的概念

Day 20 & 21-Snake Game

Day 20 & 21-Snake Game






留言討論