Vue-101-Day 10

|

使用v-on這個 directive監聽 DOM 事件以及執行 JavaScript code。

範例:

<div id="app-17">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button avoce has been clicked {{ counter }} times.</p>
</div>
var vm17 = new Vue({
  el: '#app-17',
  data: {
    counter: 0
  }
})

每當點擊 Add 1 這個 button,畫面顯示也會跟著變動

View

方法事件處理(Method Event Handler)

需要執行複雜的邏輯處理時,在 v-on 指令中撰寫 JavaScript 就顯得雜亂,所以 v-on 指令後面可以接 method name,將邏輯程式碼寫在 method 裡,會比較可行。

範例:

<div id="app-18">
  <button v-on:click="greet">Greet</button>
</div>
var vm18 = new Vue({
  el: '#app-18',
  data: {
    name: 'Vue'
  },
  methods: {
    greet: function(event) {
      alert(`Hello ${this.name}`)
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})

View

透過點擊 button 觸發事件外,也可以直接引用(e.g: vm18.greet()

 除了直接綁定 method 之外,也可以在 inline JavaScript statement 使用 method

<div id="app-19">
  <button v-on:click="say('Hi', $event)">Say Hi</button>
</div>
var vm19 = new Vue({
  el: '#app-19',
  methods: {
    say: function(message, event) {
      alert(message)
    }
  }
})

註:有時候會需要原始的 DOM Event,Vue 提供$event將這個特殊變數傳入方法

事件修飾符(Event Modifiers)

在 DOM 事件處理 event.preventDefault() 或 event.stopPropagation()是滿常見的,但是方法內純粹處理資料邏輯而不用再額外處理 DOM 事件,是比較好的處理方式,Vue 提供一些事件修飾符來解決這個問題

  • .stop:防止事件冒泡
  • .prevent:防止預設行為
  • .capture:事件捕獲
  • .self:只觸發 event.target 等於自身的 element,不是來自子元素
  • .once:事件只會觸發一次
  • .passive

stop

防止事件冒泡,也就是 event.stopPropagation()

<div id="app-20">
  <ul v-on:click="outer">
    <li v-on:click="middle">
      <a v-on:click="inner" target="_blank" href="http://google.com">
        google.com
      </a>
    </li>
  </ul>
</div>
var vm20 = new Vue({
  el: '#app-20',
  methods: {
    outer: function() {
      console.log('outer')
    },
    middle: function() {
      console.log('middle')
    },
    inner: function() {
      console.log('inner')
    }
  }
})

Vue

點擊 google.com 這個超連結時,除了觸發自身(inner)的 function 外,還會接觸發 middle、outer Event Handler 的事件 ,產出 LOG 如下

inner
middle
outer

冒泡事件順序為:inner -> middle -> outer

這時候加上.stop阻止冒泡事件,如此一來就不會觸發到 middle 及 outer 事件

<div id="app-20">
  <ul v-on:click="outer">
    <li v-on:click="middle">
      <a v-on:click.stop="inner" target="_blank" href="http://google.com">
        google.com
      </a>
    </li>
  </ul>
</div>

prevent

阻止預設行為事件

下述範例點擊完超連結後,瀏覽器會開一個新 Tab 連結到 google.com

<a target="_blank" href="http://google.com" >google.com</a>

但加上v-on:click.prevent,就可以防止連結到 google.com,阻止預設行為發生

<div id="app-20">
  <ul v-on:click="outer">
    <li v-on:click="middle">
      <a
        v-on:click.prevent="inner"
        target="_blank"
        href="http://google.com"
      >
        google.com
      </a>
    </li>
  </ul>
</div>

modifiers 修飾符可以串接

範例為 stop + prevent,阻止冒泡事件加上防止預設行為

<div id="app-20">
  <ul v-on:click="outer">
    <li v-on:click="middle">
      <a
        v-on:click.stop.prevent="inner"
        target="_blank"
        href="http://google.com"
      >
        google.com
      </a>
    </li>
  </ul>
</div>

輸出結果

inner

capture

事件捕獲(Event Capture)方向是從父元素傳到子元素,以下範例來說結果為:outer -> middle -> inner

<div id="app-20">
  <ul v-on:click.capture="outer">
    <li v-on:click.capture="middle">
      <a
        v-on:click.capture="inner"
        target="_blank"
        href="http://google.com"
      >
        google.com
      </a>
    </li>
  </ul>
</div>
var vm20 = new Vue({
  el: '#app-20',
  methods: {
    outer: function () {
      console.log('outer')
    },
    middle: function () {
      console.log('middle')
    },
    inner: function () {
      console.log('inner')
    }
  }

輸出結果

outer
middle
inner

self

觸發 event.target 等於自身的 element,而不是自子元素

範例來看:outer 及 inner 都給.self,而 middle 沒給,點擊後因為 inner 包含在 middle 裡,所以 middle 也會被觸發

<div id="app-20">
  <ul v-on:click.self="outer">
    <li v-on:click="middle">
      <a v-on:click.self="inner" target="_blank" href="http://google.com">
        google.com
      </a>
    </li>
  </ul>
</div>

輸出結果

inner
middle

once

事件只會觸發一次

範例來說:點擊一次 counter 都會+ 1,但加上 once 後,事件只觸發一次,變數 counter 值也不會變了

<div id="app-20">
  <button v-on:click="outer">Add 1</button>
  <p>Counter is {{ counter }}</p>
</div>

passive

DOM Event 產生時,瀏覽器會查詢是否有 preventDefault,因為無法預先知道,所以 passive 就是告訴瀏覽器,沒有使用 preventDefault 阻止預設行為,以利提升效能

<div v-on:scroll.passive="onScroll">...</div>

按鍵修飾符(Key modifiers)

有時候會需要監聽鍵盤事件(key board),當 key up 某個按鍵就要執行某個 method,在 Vue 可以透過 v-on監聽鍵盤事件

範例:當在 input 欄位  按下 Enter 鍵,變數 counter 值就會+1

<div id="app-21">
  <input v-on:keyup.enter="submit" />
  <p>Counter is {{ counter }}</p>
</div>
var vm21 = new Vue({
  el: '#app-21',
  data: {
    counter: 0
  },
  methods: {
    submit: function() {
      this.counter++
    }
  }
})

Key codes

另 Vue 提供了常用的 key code 名稱

  • enter
  • tab
  • delete
  • esc
  • space
  • up
  • down
  • left
  • right

System modifiers keys

支援 Vue 2.1.0 以上

  • .ctrl
  • .alt
  • .shift
  • .meta

範例

<div id="app-21">
  <input @keyup.enter="submit" @keyup.ctrl.67="clear" />
  <p>Counter is  now.</p>
</div>
var vm21 = new Vue({
  el: '#app-21',
  data: {
    counter: 0
  },
  methods: {
    submit: function() {
      this.counter++
    },
    clear: function() {
      this.counter = 0
    }
  }
})

exact 修飾符

支援 Vue 2.5.0 以上,控制精確的 System modifier keys

範例 1:Alt 及 Shift 按下皆會觸發

<button @click.ctrl="onClick">A</button>

範例 2:加上.exact後,只有 Ctrl 按下才會觸發

<button @click.ctrl.exact="onCtrlClick">A</button>

Mouse button modifiers

支援 Vue 2.2.0 以上

  • .left
  • .right
  • .middle

參考資料:

Comments