Vue 初心者筆記 #3 使用 v-on 搭配修飾符製作頁面互動行為

本篇介紹如何使用 v-on 做出頁面上的互動行為,同時也會介紹 v-on 會搭配使用到的修飾符。

v-on 基本介紹

v-on 在 jQuery 中寫成 $('xxx').on('click', function(){...}),當被綁定的 DOM 元素被點擊時,就會觸發後方 function 裡頭的事件行為。

這與 Vue 的概念不同,Vue 會把觸發事件寫在元件上,而非直接寫在 Vue 的原始碼裡面。
在 Vue 中,我們會在 HTML 元素上綁定要觸發的事件,再到 Vue app 裡面新增一個物件叫做 methods

我們透過以下兩個範例,說明 v-on 的使用方法與觀念。

範例一:反轉字串

首先我們新增一個 reverseText 的方法到 methods 物件,接著將事件透過 v-on 綁定上去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<input type="text" v-model="text" />
<button v-on:click="reverseText">反轉字串</button>
{{ newText }}
</div>

<script>
var app = new Vue({
el: '#app',
data: {
text: '',
newText: '',
},
// 新增 methods 物件
methods: {
reverseText: function () {
console.log('點我');
},
},
});
</script>

設定好 v-on 與觸發事件後,我們要讓 methods 能夠讀取 data 的資料,這時候會使用 this 來取得這個資料的屬性。
完成後這個 newText 就會是 text 字串反轉後的結果哩。

1
2
3
4
5
6
methods: {
reverseText: function(){
console.log('點我', this.text);
this.newText = this.text.split('').reverse().join(''); // 字串反轉
}
}

補充說明反轉字串的方法

剛才的 .split('').reverse().join('') 是字串反轉的一種方法,我們可以把這段程式碼拆解成以下三個步驟。

  1. .split(''):將字串以某個字或符號分割,並回傳一個陣列 (Array)
    例如:
    'Hello'.split("e") → [‘H’, ‘llo’]
    若以空白分隔,會變成 [‘H’, ‘e’, ‘l’, ‘l’, ‘o’]
  2. .reverse():把陣列裡元素的順序做顛倒
    例如:
    'Hello'.split("e").reverse → [‘llo’, ‘H’]
    若以空白分隔,會變成 [‘o’, ‘l’, ‘l’, ‘e’, ‘H’]
  3. .join():把陣列拼接成字串 (String)
    例如:
    'Hello'.split("e").reverse.join("-") → “llo-H”
    ["a", "b", "c"].join(",") → “a,b,c”

範例二:切換 ClassName

目標:透過切換 ClassName 來旋轉 box
實作方法:

  1. data 裡預定義 isRotate 資料,並使用 v-bindisRotate<div> 元素做綁定
  2. 綁定 v-onchangeRotate 事件到 <button>

如此一來當使用者點擊按鈕時,就會觸發事件並執行 this.isRotate = !this.isRotate 這段程式碼,達到動態切換 isRotate 值的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<div :class="{'rotate': isRotate }"></div>
<button v-on:click="changeRotate">切換 box 樣式</button>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
isRotate: false,
},
// 新增 methods 物件
methods: {
changeRotate: function () {
this.isRotate = !this.isRotate;
},
},
});
</scipt>

帶入參數

v-on:click 所觸發的事件也可以是帶有參數的函式。例如:每次點擊儲值按鈕都會加 500 元,且該物件按下儲值時不會影響到其他兩個物件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div id="app">
<ul>
<li v-for="item in arrayData">
{{ item.name }} 有 {{ item.cash }} 元
<button @click="storeMoney(item)">儲值</button>
</li>
</ul>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
arrayData: [
{ name: '阿翔', age: 21, cash: 500 },
{ name: '小萱', age: 23, cash: 1000 },
{ name: '漂亮阿姨', age: 30, cash: 5000 }
],
},
methods: {
storeMoney: function(item) {
item.cash = item.cash + 500;
},
}
})
</scipt>

v-on 常用修飾符

接下來要順帶講修飾符的概念,修飾符常搭配 v-on 一起使用,所以就一起介紹哩。

修飾符大致上有以下三種:

  • 事件修飾符:.stop.prevent.capture.self.once
  • 按鍵修飾符:特定鍵、別名、組合鍵
  • 滑鼠修飾符:.left.right.middle

事件修飾符

事件修飾符就是觸發事件時會順帶作用的修飾符。

.stop

.stop 其實就等同於調用 event.stopPropagation()
什麼是 stopPropagation 呢?
一般而言,觸發 DOM 元素時,是「由內而外」傳播,像是當我們想要點擊中間的 box 元素時,外面的 div 元素也會一起觸發,而它們觸發的順序會是 boxdiv

stopPropagation

但是如果我只想點擊 box,不想點到 div,該怎麼做呢?
這個時候我們可以使用 .stop 修飾符!把它加上去之後,觸發時就不會繼續向外傳播囉,也就是點擊裡面的 box 不會觸發 div 了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<div @click="trigger('div')">
<span @click.stop="trigger('box')"></span>
</div>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
// omit...
},
methods: {
trigger: function(name) {
console.log(name, '此事件被觸發了');
}
}
})
</script>

.prevent

加上 .prevent 會禁止元素原本要做的行為,其實就是調用 event.preventDefault() 而已囉。

.capture

.capture 會讓傳播順序相反,變成由外而內傳播。
例如:點擊中間的按鈕後,會回傳傳播順序相反的結果。

1
2
3
4
5
6
7
<div id="app">
<div @click.capture="trigger('div')">
<span @click.capture="trigger('box')">
<button @click.capture="trigger('button')">按我</button>
</span>
</div>
</div>

如圖,原本是由內而外傳播,現在變成由最外層的 div 先回傳結果了。

GITHUB

.self

加上 .self 修飾符能夠讓點擊時只觸發自己這個元素,而不會觸發到其他元素。

1
2
3
4
5
6
7
<div id="app">
<div @click.self="trigger('div')">
<span @click.self="trigger('box')">
<button @click.self="trigger('button')">按我</button>
</span>
</div>
</div>

.once

加上 .once 會使得事件偵聽器只觸發一次。

1
2
3
4
5
6
7
<div id="app">
<div @click.once="trigger('div')">
<span @click.once="trigger('box')">
<button @click.once="trigger('button')">按我</button>
</span>
</div>
</div>

按鍵修飾符

透過鍵盤的按鍵可以觸發的一些效果。

keyCode (keyAlias)

事件會從特定鍵觸發,鍵盤上的每個按鍵都有一個對應的編號,透過一些查詢編號網站像是JavaScript Event KeyCodes可以查到,像是 Enter = 13。

使用範例:在 keyup 後面直接加上 keyCode 號碼 (@keyup.13),按下 Enter 時就會觸發哩。

1
<input type="text" v-model="text" @keyup.13="trigger(13)" />

別名修飾

當然我們不一定要記住以上那些按鍵編號,我們也可以使用別名當作按鍵修飾符,例如:.enter.tab.delete.esc.space.up.down.left.right

像是 @keyup.space 就是只有按下 space 時才會觸發,如果是按 Enter 或其他按鍵都不會觸發事件。

1
<input type="text" v-model="text" @keyup.space="trigger('space')" />

相應按鍵(組合鍵)

只有按下相應按鍵時,才會觸發事件的監聽器,例如:.ctrl.alt.shift.meta

範例:@keyup.shift.enter 就是要同時按 Shift + Enter 才會觸發事件。
這個我在自製一些輸入框的元件時有用上,像是設計為 Enter 是換行,而 Shift + Enter 才是送出留言之類的。

1
2
3
4
5
<input
type="text"
v-model="text"
@keyup.shift.enter="trigger('shift + Enter')"
/>

滑鼠修飾符

預設點擊的是左鍵 (left),總共有以下三種滑鼠修飾符:

  • .left:只有點擊滑鼠”左鍵”時才會觸發
  • .right:只有點擊滑鼠”右鍵”時才會觸發
  • .middle:只有點擊滑鼠”中鍵”時才會觸發

範例:@click.right

1
<span class="box" @click.right="trigger('Right button')"></span>

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。