iT邦幫忙

7

[筆記][Vue.js]打開Vue.js世界的大門(9)-事件綁定的後綴修飾符Part1篇

HI!其實第一篇已經簡單介紹過事件綁定了,但是我看他官方文件上面好像還有很多可以講,就在這裡把他獨立出來了XD


再講新的之前先複習一下之前學過的綁定方式:
HTML

<div id="timeVue">
    <!--透過v-on:click綁定getTime事件,@click是簡寫-->
    <input type="button" value="點我看時間" @click="getTime"/>
</div>

JavaScript

let method = {
    //建立一個可以印出現在時間的function
    getTime : () =>{
        console.log(String(new Date()))
    }
}

let timeVue = new Vue({
    el:'#timeVue',
    //設定事件屬性的物件
    methods:method,
})

經過上面的設定,就可以簡單綁定好一個看時間的事件了:
https://ithelp.ithome.com.tw/upload/images/20180827/20106935kowCZNMQc2.jpg

有時候我們也會需要知道觸發執行事件的狀態,所謂的事件狀態是指當發生滑鼠事件時,會將MouseEvent物件傳送到事件的流程中,而那個MouseEvent就是要抓取的事件狀態(詳情看這裡),我們可以利用特殊的變數$event把他當作參數傳到function中:
HTML

<div id="timeVue">
    <!--在function中傳入參數$event-->
    <input type="button" value="點我看事件狀態" @click="getValue($event)"/>
</div>

JavaScript

let method = {
    getValue : (event) =>{
        console.log(event)
    }
}

let timeVue = new Vue({
    el:'#timeVue',
    //設定事件屬性的物件
    methods:method,
})

如下方,因為codepen不給力,無法在console寫下太大的紀錄,所以用chrome的開發者工具來看結果:
https://ithelp.ithome.com.tw/upload/images/20180827/20106935Tydh7eCIwb.jpg
事件狀態內也可以查看到觸發的DOM內容,在target屬性中:
https://ithelp.ithome.com.tw/upload/images/20180827/20106935wqcabJycJF.jpg

上面都還算很容易理解,但是下面就有點困難了,首先大家不知道還記不記得v-model他有幾個修飾符,像是等到移開焦點才觸發的.lazy,只綁定數字的.number以及去頭去尾的.trim,而v-on就更多了!讓我娓娓道來:

1. .stop

第一個出現的修飾符stop是為了防止事件冒泡(關於事件冒泡可以看這裡)而誕生的,我們看下方例子(以下用了之前提到的各種做法,但是實務上請選一種固定使用就好,不然隔壁同事的臉色會很難看XD):
HTML

<div id="ex1Vue">
    <!--綁定class和click事件-->
    <div id="outside" :class="outside" @click="clickOutside">
        <!--直接綁定style-->
        <div id="inside" :style="insideCss" @click="clickInside">
            <!--最裡面的按鈕綁定事件-->
            <input id="clickMe" type="button" value="請按我" @click="clickMe">
        </div>
    </div>
</div>

CSS

/*為外面的class設定style屬性*/
#outside{
    height:100px;
    width:200px;
    background-color:blue;
}

JavaScript

//資料
let ex1Data = {
    //設定外曾綁定的class名稱
    outside:'outside',
    //設定內層的style屬性
    insideCss:{
        height:'50px',
        width:'150px',
        backgroundColor:'red',
    },
}
//事件
let ex1Method = {
    //兩個div以及最內層的按鈕事件
    clickOutside : ()=>{
        console.log("外面")
    },
    clickInside : ()=>{
        console.log("裡面")
    },
    clickMe:()=>{
        console.log("按鈕")
    }
}
//Vue物件
let ex1Vue = new Vue({
    el:'#ex1Vue',
    data:ex1Data,
    methods:ex1Method,
})

https://ithelp.ithome.com.tw/upload/images/20180829/20106935qCrJlcYKCa.jpg
得到的結果會如上圖,因為三個DOM都重疊在一起,所以當點擊內層的按鈕時外面兩層div也會同時被點擊到,但是我們只點按鈕而已啊,不想要讓事件像上方一樣同時執行...這時候除了在事件中添加event.stopPropagation()阻止事件冒泡外,在Vue中也提供了stop修飾事件,下方把.stop加進HTML中:
HTML

<div id="ex1Vue">
    <div id="outside" :class="outside" @click="clickOutside">
        <div id="inside" :style="insideCss" @click="clickInside">
            <!--在@click後方增加stop修飾符-->
            <input id="clickMe" type="button" value="請按我" @click.stop="clickMe">
        </div>
    </div>
</div>

https://ithelp.ithome.com.tw/upload/images/20180829/20106935FzYlGm8lv3.jpg
加上stop後便只執行了按鈕的事件,就不在執行重疊到的div事件。

2. .prevent

這一個修飾符的功用在於讓DOM失去原本的功能,只執行我們幫他設定的事件,例如當我們在a標籤下事件時,他在執行完事件就會跳轉到我們設定的href網址,前情提要在這邊,但我們今天還是另外用Vue來寫一個例子(熟能生巧嘛!多多練習XD):
HTML

<div id="ex1Vue">
    <a href="URLText" @click="clickMe">{{message}}</a>
</div>

JavaScript

let ex1Data = {
    message:'跳到鐵人幫幫忙',
    URLText:'https://ithelp.ithome.com.tw/'
}

let ex1Method = {
    clickMe:()=>{
        console.log("觸發事件")
    }
}

let ex1Vue = new Vue({
    el:'#ex1Vue',
    data:ex1Data,
    methods:ex1Method,
})

https://ithelp.ithome.com.tw/upload/images/20180829/20106935brXPrYurAG.jpg
他會像上面一樣,執行完事件後就跳轉到其他頁面,不一定是a連結標籤,像type="submit"input也是會預設送出表單,他們本身標籤都會預設執行一些事件,而我們想要阻止他的時候就可以使用.prevent修飾符,他會取消所有DOM本身的預設功能,下方把他加進HTML中。
HTML

<div id="ex1Vue">
    <a href="URLText" @click.prevent="clickMe">{{message}}</a>
</div>

https://ithelp.ithome.com.tw/upload/images/20180829/20106935dHQ6T9Co8j.jpg
加上.prevent後不管我怎麼點,他也都不會跳頁了!因為a標籤的連結功能被我一個.prevent取消XD。

3. 修飾符可以連接著使用

上面都只在一個時候單獨使用一個修飾符,但是修飾符是可以像下方這樣使用的(下方只寫HTML舉簡單的例子):
HTML

<!--在修飾符後緊接著另一個修飾符-->
<a href="https://ithelp.ithome.com.tw/" @click.stop.prevent = "clickMe"></a>

這麼寫就能同時得到.stop.prevent的效果(廢話!不然幹嘛這樣寫XD),既能防止事件冒泡也能擋掉DOM的預設功能。

4. 只有修飾符

呃...這個...其實我不曉得是為了什麼/images/emoticon/emoticon16.gif,如果有用過的大大再請留言指導我一下,官方的舉例是在form上的submit使用,不曉得是不是不想讓form預設會submit,儘管他本身沒有指定事件,如下:
HTML

<form v-on:submit.prevent></form>

5. .capture

這個修飾符就和上方的.stop是反過來的,不過又有點不一樣,他會先執行擁有.capturev-on,並再從最內層依序執行到不包含自身的父元素,下方拿.stop的例子來改成.capture,觀察一下console出現的順序就可以看出端倪了:
HTML

<div id="ex1Vue">
    <!--在最外層增加.capture修飾符-->
    <div id="outside" :class="outside" @click.capture="clickOutside">
        <div id="inside" :style="insideCss" @click="clickInside">
            <input id="clickMe" type="button" value="請按我" @click="clickMe">
        </div>
    </div>
</div>

https://ithelp.ithome.com.tw/upload/images/20180829/20106935k1La6aySNr.jpg
觸發事件的順序會由有.capture修飾符的元素先,再去獲取最內部子元素的事件往母元素依序執行。

所以順序是先執行有.capture的外層div再執行最內層的按鈕事件,之後往母元素執行,但是已經執行過的最外層div就不會再執行了,所以最後執行的會是inside這個div,那這邊可以思考一下,如果我把.capture放在inside這個div的話,console會怎麼顯示呢?

6. .self

這個修飾詞會去判斷滑鼠觸發DOM事件的範圍內是否有子元素事件,如果有就執行子元素的事件,不會執行自身擁有.self修飾符的元素事件,換個說法,擁有.self的元素只會在確定點到自身DOM的時候才觸發事件,我們也可以拿.stop的例子來改一下HTML
HTML

<div id="ex1Vue">
    <!--在最外層增加.self-->
    <div id="outside" :class="outside" @click.self="clickOutside">
        <div id="inside" :style="insideCss" @click="clickInside">
            <input id="clickMe" type="button" value="請按我" @click="clickMe">
        </div>
    </div>
</div>

https://ithelp.ithome.com.tw/upload/images/20180829/20106935ivtr3u14Vj.jpg
當我點擊按鈕的時候,正常來說會觸發到一個按鈕和兩個div,但是最外層的div含有.self修飾符,所以當我們不是直接點擊他,而是透過事件冒泡去處發是會被.self給擋下來的,只有在直接點擊外層div的時候才會執行事件,如下圖:
https://ithelp.ithome.com.tw/upload/images/20180829/201069358aFuiElKgi.jpg


今天提到的4個修飾符及2個小用法是Vue.js初代版就有的功能,當然啦!他之後又新增了一些很方便的修飾符,讓我們把初代和後代給劃開(其實是小弟我愛睏了,嗚嗚...),下一篇文章的事件綁定Part3在來提剩下的修飾符功能,Vue.js的基本篇目測應該就剩兩篇了XD,如果學習的過程中有問題還請各位大大多包涵。

最後如果文章中有哪裡解釋不清楚或是理解錯誤的地方,還麻煩各位大大留言告訴我,我會盡快修正或補充文章內容,也感謝大大們的觀看!謝謝/images/emoticon/emoticon41.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
Homura
iT邦高手 1 級 ‧ 2018-08-30 14:31:30

這些功能真不錯
又上了一課/images/emoticon/emoticon12.gif
之前玩時實在太多東西
只找想要的/images/emoticon/emoticon06.gif

神Q超人 iT邦研究生 5 級 ‧ 2018-08-30 16:37:55 檢舉

官網真的寫得非常清楚,
不過相對的也很多,
多到一不小心就會放棄讀完,哈哈哈XD
只是想說難得有機會記錄,就全部試一遍寫下來/images/emoticon/emoticon33.gif

原來上一篇是鋪陳。 /images/emoticon/emoticon01.gif

神Q超人 iT邦研究生 5 級 ‧ 2018-08-31 00:54:49 檢舉

哈哈哈!對啊!全部塞在這篇文章講怕會離題XD

0
Nick
iT邦新手 5 級 ‧ 2018-11-12 15:18:58

我的經驗是 form 在 html 預設裡面 submit 會把整個頁面 refresh,後面的 method 還沒執行就刷新了,所以才會加上 prevent 來防止頁面重整

神Q超人 iT邦研究生 5 級 ‧ 2018-11-12 19:02:45 檢舉

所以在單單只有修飾符的狀態下
也是會和prevent這個一樣嗎?
就不讓submit預設把表單送出/images/emoticon/emoticon19.gif

1
Cynthia
iT邦新手 5 級 ‧ 2019-03-04 14:43:39

奇怪,我使用你程式碼

<a href="URLText" 

結果,他由http://127.0.0.1:8080/導向了http://127.0.0.1:8080/URLText#/

要用

<a v-bind:href="URLText"

才會真的導向我在URLText中設定的網址

神Q超人 iT邦研究生 5 級 ‧ 2019-03-05 00:24:30 檢舉

不好意思!這邊是我疏忽了!
應該是要使用 v-bind 綁定 data 中的資料沒有錯!
感謝大大幫忙/images/emoticon/emoticon41.gif

0
kkdayy_55330
iT邦新手 5 級 ‧ 2019-03-31 14:21:29

嗨大大您好

所以 submit.prevent 是要做什麼事情呢?

我要留言

立即登入留言