iT邦幫忙

4

[筆記][Vue.js]打開Vue.js世界的大門(6)-讓watch來當你的眼睛!

  • 分享至 

  • xImage
  •  

HI!大家好啊!緊接著computed之後,今天再來學習新的Vue.js的屬性watch吧!


watch

這是什麼?

如果我們要在一個表單上的值發生改變的時候,去執行某些事件,例如判斷輸入資料的格式正不正確,第一個想到的應該是以下的做法:
HTML

<div id="nameVue">
    <input id="name" v-model="name" @change="checkName" />
  <span style="color:red">{{alertMessage}}</sapn>
</div>

JavaScript

//資料
let nameData = {
    name : 'Tom Cruise',
    alertMessage : '',
}

//方法
let nameMethod = {
    //檢查姓名格式
    checkName : () => {
        let newName = document.getElementById('name').value
        if(newName.trim().indexOf(' ') == -1){
            nameData.alertMessage = '請輸入正確的姓名格式'
        }
        else
            nameData.alertMessage = ''
    }
}

let nameVue = new Vue({
    el:'#nameVue',
    data:nameData,
    methods:nameMethod,
})

我們可以透過v-on來處理onchange事件,達到我們要的成果:
https://ithelp.ithome.com.tw/upload/images/20180824/20106935BajbM7aFH7.jpg
但是如果我們使用onchange事件的話,就必須在移除焦點時才會觸發相對應的事件,那有辦法在值改變的時候就馬上知道嗎?

欸嘿嘿!有的!接著讓我們把watch給請出來吧!

watch的基本用法

基本上watch能夠在某個監聽值發生改變的時候進行異步的響應,有點類似JavaScript上的監聽器addEventListener(),不過他是對物件內的值做監聽,來看看使用方法吧!
HTML

<div id="nameVue">
    <input id="name" v-model="name"/>
    <span style="color:red">{{alertMessage}}</sapn>
</div>

JavaScript

//資料
let nameData = {
    name : 'Tom Cruise',
    alertMessage : '',
}

//方法
let nameMethod = {
    //檢查姓名格式
    checkName : (newName,oldName) => {
        if(newName.trim().indexOf(' ') == -1)
            nameData.alertMessage = '請輸入正確的姓名格式'
        else
            nameData.alertMessage = ''
    }
}

let nameVue = new Vue({
    el:'#nameVue',
    data:nameData,
    watch:{
        /*對name值進行監聽,只要name改變了,就會觸發程式
        newVal為更改後的值,oldVal更改前的值*/
        name: (newVal,oldVal) => {
            //呼叫nameMethod的function
            nameMethod.checkName(newVal)
        }
    }
})

上方例子中,我們原本綁定在input@change拿掉,並在Vue的物件中增加了一個新的物件屬性watchwatch中的name屬性即是要進行監聽的屬性,並在屬性值改變時執行function,另外可以發現,在執行的function中有兩個參數newValoldVal,這兩個參數是Vue幫忙處理的,第一個參數傳入更改過後的值,第二個為更改前的值,經過以上方式,即使在輸入中也可以捕捉每一次和前一次變動的內容,以及變動時要使用的函式,便不需要在離開焦點才能執行function看到結果,如下:
https://ithelp.ithome.com.tw/upload/images/20180825/20106935xBZD1RkDvX.jpg

補充說明(感謝fysh711426大大補充)

watch的運作主要是因為v-model幫我們做了兩件事情

  1. 使用v-bind單向綁定資料,會因為每次綁定值的變動同步更新到View上。
  2. 使用v-on:input去偵測每次值的變動,觸發更新v-bind綁定的值。

參考文章:https://blog.csdn.net/u010320804/article/details/79486034
以上補充也會同步更新到[筆記][Vue.js]打開Vue.js世界的大門(4)-讓雙向綁定抓住你的資料

watch的原理是因為v-model幫我們做了v-on:input的關係,這會導致我們每次的更新資料的時候,都重新把新值透過存取器的setter寫到綁定的屬性中,主角watch就會在這個時候藉由setter觸發,執行watch中綁定的事件,執行完後後再用getter把值重新綁定到畫面!

參考文章:https://segmentfault.com/a/1190000010014281


話說,官方在說明watch的例子時真的很簡單就帶過了,感覺對他有點偏心XD,不過以上表單驗證的例子也是我目前想的到watch在實務上可以用到的地方,其他可能要等到某天預到什麼需求,才會想起「對了!我可以用watch處理!」這樣子吧XD,如果有大大在實務上watch應用的地方也歡迎留言分享!

最後這篇短短的watch屬性應該不難懂(結果我也偏心給他最少的章節XD)!如果文章中有任何解釋錯誤、講解不清楚的地方,在請各位大大留言告訴我,我會盡快修改文章內容的!謝謝大家的觀賞/images/emoticon/emoticon41.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
小魚
iT邦大師 1 級 ‧ 2018-08-25 01:22:04

你該不會在準備鐵人賽的資料吧
/images/emoticon/emoticon39.gif

看更多先前的回應...收起先前的回應...
神Q超人 iT邦研究生 5 級 ‧ 2018-08-25 11:57:50 檢舉

已經發過的文章應該不能在放鐵人賽吧XD
不過我倒是有想說用React參賽/images/emoticon/emoticon37.gif

小魚 iT邦大師 1 級 ‧ 2018-08-25 13:09:31 檢舉

沒規定不行啊
/images/emoticon/emoticon39.gif

神Q超人 iT邦研究生 5 級 ‧ 2018-08-26 01:15:14 檢舉

哈哈哈,小魚大大我們一起參賽啊XD

小魚 iT邦大師 1 級 ‧ 2018-08-26 08:11:25 檢舉

今年有參加啊,明年看有沒有時間吧,還沒想到要用什麼主題...要不然unity也是可以,只是怕學習速度沒那麼快...不過可以把現在學的到時候拿出來用...
/images/emoticon/emoticon39.gif

神Q超人 iT邦研究生 5 級 ‧ 2018-08-26 10:40:23 檢舉

我也很怕沒時間,哈哈哈。
大大下手unity了哦!很期待開發出來的遊戲XD

小魚 iT邦大師 1 級 ‧ 2018-08-26 10:59:43 檢舉

目前還在摸2D而已,還沒進展到3D的階段...

2
小碼農米爾
iT邦高手 1 級 ‧ 2018-08-25 16:22:38

好奇去查了一下 watch 的原理,細節感覺蠻深奧的,有機會再深入研究,哈哈哈。
不過大致流程如下:

  • 使用者輸入文字,觸發 oninput 事件。
  • Vue 接收到事件觸發 v-model 更新 name 的值。
  • name 透過 setter 觸發 watch。
  • watch 內呼叫 checkName 更改 alertMessage。
  • alertMessage 透過 setter 觸發 watch。
  • Vue 將 watch 推入佇列中等待更新。
  • JS 執行完畢後,統一取出 watch 更新 DOM。
神Q超人 iT邦研究生 5 級 ‧ 2018-08-25 17:10:11 檢舉

對耶!
我沒有注意到這點/images/emoticon/emoticon17.gif
我有試著把上方的@change改成@input果然就可以得到和watch一樣的效果了!
之前都沒有注意過這個事件/images/emoticon/emoticon20.gif
我會再修改一下文章中的內容,感謝大大補充!

哈哈哈,我也是今天查資料才發現 oninput 事件,textbox 會觸發 oninput 其實是因為 v-model 的語法糖。

<input v-model="name" />
//等於
<input v-bind:value="name" v-on:input="name=$event.target.value" />
神Q超人 iT邦研究生 5 級 ‧ 2018-08-26 01:30:49 檢舉

真的很感謝大大的補充,
我已經把查到的資訊放到文章中了!
如果有理解錯的話還麻煩大大告訴我/images/emoticon/emoticon41.gif

話說其實我一直沒有去研究過Vue的生命週期是怎麼運作,
想說之後是不是應該要發一篇文來講這個東西/images/emoticon/emoticon13.gif

我要留言

立即登入留言