Vue.js事件

by vivid 24. 七月 2019 07:31

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N190720902
出刊日期:2019/7/24

在這篇文章將延續本站《Vue.js入門》系列文章,來介紹如何透過Vue來註冊事件。

JavaScript利用事件(Event)和網頁中的HTML項目進行互動,例如,當使用者利用滑鼠點選網頁中的項目時,就會觸發此項目的Click事件,我們可以撰寫程式碼來註冊接聽這個事件,在接聽的事件「click」發生時,執行特定的程式碼,這段程式碼稱為事件接聽程式(Event Listener)。

Vue提供簡易的「v-on」指示詞,或透過「@」符號來註冊並接聽DOM物件的事件。參考以下範例程式碼,<h1>標籤使用了「v-on:click」註冊了「click」事件,將之繫結到「showMsg」函式,此函式的名稱可以自訂。當事件發生時,就會叫用「showMsg」並執行函式,顯示「Hello World」訊息方塊:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <h1 v-on:click="showMsg"> {{ msg }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script >
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello World'
      },
      methods:{
        showMsg : function (event) {
          alert(this.msg);
          if (event) {
            alert(event.target.tagName);
          }
        }
      }
    });
  </script>
</body>

</html>

 

在「showMsg」函式之中,若想要存取「event」物件,可以在「showMsg」函式宣告一個「event」參數,如此就可以利用「event.target.tagName」來取得觸發事件的HTML項目,這個範例程式的執行結果參考如下:

clip_image002[4]

圖 1:註冊Click事件。

「@」符號則是「v-on」指示詞替代性的簡易語法,上述的範例,我們也可以改用以下語法來註冊「click」事件,得到相同的執行結果:

<h1 @click="showMsg"> {{ msg }} </h1>

使用方法叫用事件處理常式

除了直接透過上述使用事件繫結的方式來註冊事件處理常式之外,你也可以直接在事件發生時,在「v-on:click」直接叫用函式,也可以傳遞參數到函式之中,參考以下範例程式碼,直接叫用「showMsg」函式傳入「mary」字串當參數:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <h1 v-on:click="showMsg('mary')"> {{ msg }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello World'
      },
      methods: {
        showMsg: function (userName) {
          alert(this.msg + "," + userName);
        }
      }
    });
  </script>
</body>

</html>

 

存取event物件

在JavaScript中,通常使用event物件來取得觸發事件的物件(Event Target),以及事件的類型。而在Vue之中,若想要在事件處理常式之中,存取到「event」物件,那麼在「v-on:click」叫用函式時,可以使用一個特殊的關鍵字:「$event」。參考以下範例程式碼,將「$event」關鍵字傳入「showMsg」函式的第二個參數,而在「showMsg」函式之中就可以使用「event.target.tagName」取得觸發事件的HTML項目的標籤名稱:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <h1 v-on:click="showMsg('mary' , $event)"> {{ msg }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello World'
      },
      methods: {
        showMsg: function (userName ,event) {
          alert(this.msg + "," + userName);
          if (event) {
            alert(event.target.tagName);
          }
        }
      }
    });
  </script>
</body>

</html>

 

這個範例程式的執行結果參考如下,先顯示出「Hello Wrold,mary」訊息:

clip_image004[4]

圖 2:使用事件物件。

接著將顯示觸發事件的<h1>項目的標籤名稱,請參考下圖所示:

clip_image006[4]

圖 3:取得觸發事件的HTML項目的標籤名稱。

「mouseenter」與「mouseleave」事件

參考以下範例程式碼,底下的範例則是展示了「mouseenter」與「mouseleave」事件,網頁中包含一個<h1>標籤,其樣式使用「v-bind:style」繫結到一個「myStyle」物件,預設其背景顏色是白色的。在「mouseenter」事件中,我們將其前景設定為「white」;將背景顏色設定為「blue」;而在「mouseleave」事件中,我們將其前景設定為「blue」;將背景顏色設定為「white」:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <h1 v-bind:style="myStyle" @mouseenter="highLight" @mouseleave="noHighLight"> {{ msg }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello World',
        myStyle :{
          backgroundColor : "white",
          color : "blue"
        }
      },
      methods: {
        highLight: function (event) {
          this.myStyle.backgroundColor = "blue";
          this.myStyle.color = "white";
        },
        noHighLight: function (event) {
          this.myStyle.backgroundColor = "white";
          this.myStyle.color = "blue";
        }
      }
    });
  </script>
</body>

</html>

 

這個範例程式的執行結果參考如下,當滑鼠游標移動進入到<h1>標籤時,將觸發「mouseenter」事件,接著便會執行「highLight」函式;我們利用個函式來變更<h1>標籤的前景、背景顏色為白字、藍底:

clip_image008[4]

圖 4:「mouseenter」事件。

當滑鼠游標移動離開<h1>標籤時,將觸發「mouseleave」事件,接著便會執行「noHighLight」函式,函式中的程式將變更<h1>標籤的前景、背景顏色為藍字、白底:

clip_image010[4]

圖 5:「mouseleave」事件。

事件修飾詞

「v-on」attribute可以搭配事件修飾詞來變更事件註冊的行為。這些修飾詞包含:

  • 「prevent」:擋掉HTML項目預設的行為,效果同叫用JavaScript的「event. preventDefault」函式。
  • 「stop」:停用事件傳遞,效果同叫用JavaScript的「event. stopPropagation」函式。
  • 「capture」:使用event capture機制傳遞事件。
  • 「once」:事件只執行一次。
  • 「self」:只觸發event.target本身的事件。
  • 「passive」:指定是否要優化頁面滑動的流暢度。

事件修飾詞:prevent

在JavaScript中我們通常會利用「event.preventDefault()」函式來擋掉HTML項目預設的行為。例如以下範例程式碼,當你點選網頁中的超連結時,將顯示「No redirect !」訊息,並叫用「event.preventDefault()」函式,讓超連結預設導向其它網址的行為失效,網頁會停留在這個畫面:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <a href="http://www.microsoft.com" @click="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("No redirect !");
          event.preventDefault();

        }
      }
    });
  </script>
</body>

</html>

 

而在Vue之中,只需要透過「prevent」事件修飾詞,便可達成這樣的效果,參考以下範例程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <a href="http://www.microsoft.com" @click.prevent="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("No redirect !");
        }
      }
    });
  </script>
</body>

</html>

 

事件修飾詞:stop

「stop」事件修飾詞用來停止事件傳遞。我們先來看一個範例,網頁中<div>標籤内包含一個<a>標籤,我們同時為這兩個HTML項目註冊了「click」事件,顯示提示訊息:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg" @click="showMsg2">
    <a href="http://www.microsoft.com" @click="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("Anchor");
        },
        showMsg2: function (event) {
          alert("Div");
        }
      }
    });
  </script>
</body>

</html>


 

當網頁執行時,根據泡沫上升事件機制,會先顯示出「Anchor」,再顯示「Div」訊息,然後便導向<a>標籤「href」指定的網站。讓我們修改範例如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg" @click="showMsg2">
    <a href="http://www.microsoft.com" @click.stop="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("Anchor");
        },
        showMsg2: function (event) {
          alert("Div");
        }
      }
    });
  </script>
</body>

</html>

 

再次執行網頁,這次會先顯示出「Anchor」,然後便直接導向<a>標籤「href」指定的網站。不會根據泡沫事件上升的規則,觸發<div>標籤的「click」事件,也就是說觸發<a>的「click」事件之後,便停止事件了。

串接事件修飾詞

事件修飾詞可以多個串接在一起使用,例如修改上個範例,改寫成利用「@click.stop.prevent」註冊「click」事件:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg" @click="showMsg2">
    <a href="http://www.microsoft.com" @click.stop.prevent="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("Anchor");
        },
        showMsg2: function (event) {
          alert("Div");
        }
      }
    });
  </script>
</body>

</html>


 

當這個網頁執行時,只會顯示「Anchor」訊息,接著便停止事件泡沫式上傳,不顯示其它訊息,也不會導向<a>標籤「href」指定的網站。

事件修飾詞:capture

和泡沫上升由內層標籤事件,往外觸發外層標籤事件的行為恰好相反,event capture事件傳遞機制是先觸發外層標籤事件,再觸發內層標籤事件。參考以下範例程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg" @click.capture="showMsg2">
    <a href="http://www.microsoft.com" @click.capture="showMsg" target="_blank">Go To Microsoft</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
      },
      methods: {
        showMsg: function (event) {
          alert("Anchor");
        },
        showMsg2: function (event) {
          alert("Div");
        }
      }
    });
  </script>
</body>

</html>

 

當網頁執行時,根據event capture事件機制,會先顯示出「Div」,再顯示「Anchor」訊息,然後便導向<a>標籤「href」指定的網站。

事件修飾詞:once

「once」事件修飾詞,用來指定事件只執行一次,參考以下範例程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <h1 v-on:click.once="showMsg"> {{ msg1 }} </h1>
    <h1 v-on:click="showMsg"> {{ msg2 }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello',
        msg1: 'Click Once!',
        msg2: 'Click'
      },
      methods: {
        showMsg: function (event) {
          alert(this.msg);
        }
      }
    });
  </script>
</body>

</html>

 

這個範例程式的執行結果參考如下,點選第一個標題時,只有第一次會顯示「Hello」訊息;而第二個標題則每次點選,都會顯示「Hello」訊息:

clip_image012[4]

圖 6:事件修飾詞:once。

事件修飾詞:self

不管泡沫事件,或event capture,指定「self」事件修飾詞,就只會觸發event.target本身的事件。參考以下範例程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div v-bind:style="style2" id="divMsg" @click.self="showMsg2">
    <a v-bind:style="style1" href="http://www.microsoft.com" @click.self="showMsg" target="_blank">Go To Microsoft</a>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        style2: {
          width: '200px',
          height: '200px',
          backgroundColor: 'yellow'
        },
        style1: {
          width: '100px',
          height: '100px',
          backgroundColor: 'pink'
        }
      },
      methods: {
        showMsg: function (event) {
          alert("Anchor : " + event.target.tagName);
        },
        showMsg2: function (event) {
          alert("Div :" + event.target.tagName);
        }
      }
    });
  </script>
</body>

</html>

 

我們幫外層的<div>標籤搭配「self」修飾詞,註冊了「click」事件,並利用樣式指定寬、高,把背景顏色設定為黃色;內層的<a>標籤也搭配「self」修飾詞,註冊了「click」事件,並利用樣式把背景顏色設定為粉紅色:

clip_image014

圖 7:事件修飾詞:self。

當點選粉紅色區塊(<a>),只會跳出以下訊息:

clip_image016

圖 8:事件修飾詞:self。

當點選黃色區塊(<div>),只會顯示以下訊息:

clip_image018

圖 9:事件修飾詞:self。

鍵盤與滑鼠事件

在網頁中,當使用者利用鍵盤輸入資料時,會觸發鍵盤事件。Vue提供許多按鍵修飾詞(Key Modifier)來變更鍵盤事件的行為。常用的修飾詞包含:enter、tab、delete、esc、space、up、down、left、right、ctrl、alt、shift等等。

以下範例程式碼註冊文字方塊的「keyup」事件,每次在文字方塊上輸入任意按鍵,再放開時,觸發「keyup」事件,並將輸入在文字方塊中的文字顯示在下方<div>標籤:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>
  <div id="divMsg">
    <input type="text" v-on:keyup="showMsg">
    <div>{{result}}</div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        result: ''
      },
      methods: {
        showMsg: function (event) {
          this.result = event.target.value;
        }
      }
    });
  </script>
</body>

</html>

這個範例程式的執行結果參考如下:

clip_image020

圖 10:「keyup」事件。

若我們想要在輸入「Hello」字串後,直到按下「ENTER」鍵時,再將文字方塊輸入的字串顯示在下方,則可以修改事件註冊程式如下,使用「enter」修飾詞:

<input type="text" v-on:keyup.enter="showMsg">

也可以改用keyCode來修飾,例如「ENTER」鍵的keyCode為「13」,改寫事件註冊程式如下:

<input type="text" v-on:keyup.13="showMsg">

若想要在輸入「Hello」字串後,按下「Home」鍵時,再將文字方塊輸入的字串顯示在下方,則可以修改事件註冊程式如下:

<input type="text" v-on:keyup.home="showMsg">

想查詢按鍵的名稱可以參考以下網址的「KeyboardEvent.key」:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values

不過要注意,KeyboardEvent.key 名稱中的英文字使用Pascal命名法(英文字第一個字元大寫做區隔),你需要轉換成kebab-case命名法,即英文字全部使用小寫,兩個英文字之間使用「-」號區隔,例如「CapsLock」要寫成:

<input type="text" v-on:keyup.caps-lock="showMsg">

你也可以使用組合鍵,例如修改事件註冊程式如下,在按下「alt」+ 「1」時(1的keyCode為49),才將訊息顯示在下方:

<input type="text" v-on:keyup.alt.49="showMsg">

Tags:

.NET Magazine國際中文電子雜誌 | JavaScript | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List