# 事件处理

# 监听事件

<div>
  <button v-on:click="counter += 1">Add 1</button>
  <p>Counter: {{ counter }}</p>
</div>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      counter: 0
    }
  })
</script>

# 事件处理方法

v-on:可以简写为@

<button @click="greet">Greet</button>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      counter: 0
    },
    methods: {
      greet: function(event) {
        alert('Hello');
        if (event) {
          alert(event.target.tagName)
        }
      }
    }
  })
</script>

# 内联方法传参

<button v-on:click="say('hi')">Say Hi</button>
<button v-on:click="say('No', $event)">Say No</button>
<script>
  ...
  say: function(msg, event) {
    alert(msg);
    if (event) {
      alert(event.target.innerHTML);
    }
  }
  ...
</script>

# 事件修饰符

在处理事件中调用 event.preventDefalt() 或 event.stopPropagation()式非常常见的。Vue提供了更好的方式来实现。方法只关系数据逻辑,而不区处理dom细节,事件修饰符:

  • .stop 阻止事件继续传播
  • .prevent 阻止事件默认行为
  • .capture 捕获阶段触发事件
  • .self event.target === self 仅自己点击,不能是子元素点击触发
  • .once 事件只触发一次
  • .passive 表示处理函数中不会调用event.preventDefault(),事件处理函数不会阻塞默认行为(比如滚动),可以理解为事件处理函数和默认行为异步执行。
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件只触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<div v-on:scroll.passive="onScroll">...</div>

v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

# 按键修饰符

监听键盘输入时,经常需要检查详细的按键,v-on在监听键盘事件时添加按键修饰符

  • .enter
  • .tab
  • .delete (删除键和退格键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right 输入框监听事件顺序:keydown => keypress => textInput(event.data匹配值也可阻止默认输入内容) => keyup
<!-- 只有在点击的键key为 'Enter'时调用 vm.submit() -->
<input v-on:keyup.enter="submit">

<!-- 处理函数只会在 $event.key 等于 PageDown 时被调用 -->
<input v-on:keyup.page-down="onPageDown">

# 系统修饰键

  • .ctrl
  • .alt
  • .shift
  • .meta windows键或mac的command键
  • .exact 准确的控制
<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

# 鼠标按钮修饰符

限制修饰符处理函数仅使用特定的鼠标按钮

  • .left
  • .right
  • .middle
<!-- mousedown => mouseup => click -->
<!-- 监听右键点击事件, JS原生根据event.button === 2来判断  -->
<div id="app">
  <div @click.right="greet" 
      style="width:100px; height:100px; border: 1px solid #ccc;"></div>
</div>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
      counter: 0
    },
    methods: {
      greet: function(event) {
        alert('Hello');
        if (event) {
          alert(event.target.tagName);
        }
      }
    }
  })
</script>

# 为什么在HTML中监听事件

这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:

  • 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
  • 无须在 JavaScript 里手动绑定事件,ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
  • 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。
上次更新: 2020/10/29 22:59:19