• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 事件处理

    监听事件

    使用v-on指令(缩写为@符号)来监听 DOM 事件,并在触发事件时,执行一些 JavaScript。用法:

    v-on:click="methodName"
    
    // 或使用快捷方式
    @click="handler"
    


    事件处理器的值可以是:

    • 内联事件处理器:事件被触发时,执行的内联 JavaScript 语句(与 onclick 类似)。
    • 方法事件处理器:一个组件定义的方法名、或对某个方法的访问路径。


    模板编译器,会通过检查v-on的值,是否是合法的 JavaScript 标识符或属性访问,来断定是何种形式的事件处理器。举个例子,foofoo.barfoo['bar']会被视为方法事件处理器,而foo()count++会被视为内联事件处理器。


    内联事件处理器

    内联事件处理器,通常用于简单场景,例如:

    const count = ref(0)
    
    <button @click="count++">Add 1</button>
    <p>Count is: {{ count}}</p>
    


    在内联处理器中调用方法

    除了直接绑定方法名,你还可以在内联事件处理器中调用方法。这允许我们向方法传入自定义参数以代替原生事件:

    function say(message) {
      alert(message)
    }
    
    <button @click="say('hello')">Say hello</button>
    <button @click="say('bye')">Say bye</button>
    


    在内联事件处理器中访问事件参数

    有时需要在内联事件处理器中,访问原生 DOM 事件。你可以向该处理器方法传入一个特殊的$event变量,或者使用内联箭头函数

    template
    <!-- 使用特殊的 $event 变量 -->
    <button @click="warn('Form cannot be submitted yet.', $event)">
      Submit
    </button>
    
    <!-- 使用内联箭头函数 -->
    <button @click="(event) => warn('Form cannot be submitted yet.', event)">
      Submit
    </button>
    
    js
    function warn(message, event) {
      // `这里可以访问 DOM 原生事件`
      if (event) {
        event.preventDefault()
      }
      alert(message)
    }
    


    多事件处理器

    事件处理程序中可以有多个方法,这些方法由,(逗号)分隔:

    <!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
    <button @click="one($event) , two($event)">
     Submit
    </button>
    
    function one(event) {
        // first handler logic...
    }
    function two(event) {
        // second handler logic...
    }
    


    方法事件处理器

    随着事件处理器的逻辑变得愈发复杂,内联代码方式变得不够灵活。因此v-on也可以接受一个方法名或对某个方法的调用。

    const name = ref('Vue.js')
    
    function greet(event) {
      alert(`Hello ${name.value}!`)
      // `event` 是 DOM 原生事件
      if (event) {
        alert(event.target.tagName)
      }
    }
    
    <!-- `greet` 是上面定义过的方法名 -->
    <button @click="greet">Greet</button>
    

    方法作事件处理器,会自动接收原生 DOM 事件,并触发执行。在上面的例子中,我们能够通过被触发事件的event.target.tagName访问到该 DOM 元素。


    DOM 事件冒泡

    DOM 在触发事件后,会经历事件捕获和事件冒泡两个最重要阶段。在 W3C 标准中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达 document。浏览器 IE 只支持事件冒泡。

    • 事件捕获:由最外层向最里层触发事件的过程,叫事件捕获。事件从最不精确的 document 对象,开始触发,然后到最具体的元素。
    • 事件冒泡:事件会从最内层的元素开始发生,一直向外层(向上)传播,直到 document 对象。
    • 阻止冒泡:事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。阻止事件冒泡的三种手段:
      • return false:可以阻止默认事件和冒泡事件。
      • event.stopPropagation:可以阻止冒泡事件,但是允许默认事件。IE 下event.cancelBubble = true
      • event.preventDefault():可以阻止默认事件,但是允许冒泡事件。IE 下event.returnValue = false
    • 事件委托:事件委托也叫事件代理,“事件代理”即是把原本需要绑定在子元素的响应事件(onclick,onmouseover,onmouseout等)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是 DOM 元素的事件冒泡。


    事件修饰符

    在处理事件时调用event.preventDefault()event.stopPropagation()是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑,而不用去处理 DOM 事件的细节,会更好。

    为解决这一问题,Vue 为v-on提供了事件修饰符。修饰符是用.(点)表示的指令后缀。

    • .stop:阻止事件冒泡。阻止事件向上级 DOM 元素传递。
    • .prevent:阻止默认事件。默认事件,指对 DOM 的操作会引起自动执行的动作。比如,点击超链接的时候会进行页面的跳转,点击表单提交按钮时会重新加载页面等。
    • .capture:使用事件的捕获模式。使事件触发,从包含这个元素的顶层,开始往下触发。
    • .self:只有 event.target 是当前操作的元素时,才触发事件。
    • .once:事件只触发一次。
    • .passive:事件的默认行为立即执行,无需等待事件回调执行完毕。
    <!-- 阻止单击事件继续传播 -->
    <a @click.stop="doThis"></a>
    
    <!-- 提交事件不再重载页面 -->
    <form @submit.prevent="onSubmit"></form>
    
    <!-- 修饰符可以串联 -->
    <a @click.stop.prevent="doThat"></a>
    
    <!-- 只有修饰符 -->
    <form @submit.prevent></form>
    
    <!-- 添加事件监听器时使用事件捕获模式 -->
    <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
    <div @click.capture="doThis">...</div>
    
    <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
    <!-- 即事件不是从内部元素触发的 -->
    <div @click.self="doThat">...</div>
    
    使用修饰符时,需要注意调用顺序,因为相关代码是以相同的顺序生成的。因此使用@click.prevent.self会阻止元素内的所有点击事件而@click.self.prevent则只会阻止对元素本身的点击事件。


    .capture.once,和.passive修饰符与原生addEventListener事件相同:

    <!-- 添加事件监听器时,使用 `capture` 捕获模式 -->
    <!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 -->
    <div @click.capture="doThis">...</div>
    
    <!-- 点击事件最多被触发一次 -->
    <a @click.once="doThis"></a>
    
    <!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 -->
    <!-- 以防其中包含 `event.preventDefault()` -->
    <div @scroll.passive="onScroll">...</div>
    

    .passive修饰符一般用于触摸事件的监听器,可以用来改善移动端设备的滚屏性能。

    请勿同时使用.passive.prevent,因为.prevent会被忽略并且你的浏览器可能会抛出警告。请记住,.passive是向浏览器表明你不想阻止事件的默认行为。并且如果你这样做,可能在浏览器中收到一个警告。


    按键修饰符

    在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许在v-on@监听按键事件时,添加按键修饰符。

    <!-- 仅在 `key` 为 `Enter` 时调用 `vm.submit()` -->
    <input @keyup.enter="submit" />
    

    你可以直接使用KeyboardEvent.key暴露的按键名称作为修饰符,但需要转为kebab-case形式。

    <input @keyup.page-down="onPageDown" />
    

    在上述示例中,处理函数只会在$event.key等于'PageDown'时被调用。

    按键别名

    Vue 为最常用的键提供了别名:

    • .enter
    • .tab
    • .delete(捕获“删除”和“退格”键)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right


    系统修饰键

    可以用如下修饰符来实现,仅在按下相应按键时,才触发鼠标或键盘事件的监听器。

    • .ctrl
    • .alt
    • .shift
    • .meta
    在 Macintosh 键盘上,meta 是 Command 键(⌘)。在 Windows 键盘上,meta 键是 Windows 键(⊞)。在 Sun 微机系统键盘上,meta 是钻石键(◆)。在某些键盘上,特别是 MIT 和 Lisp 机器的键盘及其后代版本的键盘,如 Knight 键盘,space-cadet 键盘,meta 都被标记为“META”。在 Symbolics 键盘上,meta 也被标识为“META”或“Meta”。
    <!-- Alt + Enter -->
    <input @keyup.alt.enter="clear" />
    
    <!-- Ctrl + Click -->
    <div @click.ctrl="doSomething">Do something</div>
    
    请注意修饰键与常规按键不同,在和keyup事件一起用时,事件触发时,修饰键必须处于按下状态。换句话说,keyup.ctrl只有在按住ctrl的情况下,但松开了另一个键时,才被触发。而单单释放ctrl也不会触发事件。


    .exact修饰符

    .exact修饰符,允许控制触发一个事件所需的确定组合的系统按键修饰符。

    <!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
    <button @click.ctrl="onClick">A</button>
    
    <!-- 有且只有 Ctrl 被按下的时候才触发 -->
    <button @click.ctrl.exact="onCtrlClick">A</button>
    
    <!-- 没有任何系统修饰符被按下的时候才触发 -->
    <button @click.exact="onClick">A</button>
    

    上篇:列表渲染

    下篇:表单输入绑定