# vue - 事件修饰符:.prevent,.passive,.stop

Vue.js 为 v-on 提供了事件修饰符,让我们可以轻松的处理 event.preventDefault()event.stopPropagation()。实现:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

提供了这些修饰符:

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

# .stop

.stop 是阻止事件继续传递,可以是冒泡,也可以是捕获阶段。

<div @click="log(1)" @click.capture="log(11)" style="background-color: #00b0ff;padding: 10px">
  <div @click="log(2)" @click.capture="log(22)" style="background-color: #0bb69f;padding: 10px">
    <div @click="log(3)" @click.capture="log(33)" style="background-color: #0d47a1;padding: 10px">
      <a @click.stop="log(4)" @click.capture="log(44)" href="javascript: console.log('x')" style="color: white">
        点击
      </a>
    </div>
  </div>
</div>
1
2
3
4
5
6
7
8
9

输出:11 22 33 44 4 x

<div @click="log(1)" @click.capture="log(11)" style="background-color: #00b0ff;padding: 10px">
  <div @click="log(2)" @click.capture="log(22)" style="background-color: #0bb69f;padding: 10px">
    <div @click="log(3)" @click.capture="log(33)" style="background-color: #0d47a1;padding: 10px">
      <a @click="log(4)" @click.capture.stop="log(44)" href="javascript: console.log('x')" style="color: white">
        点击
      </a>
    </div>
  </div>
</div>
1
2
3
4
5
6
7
8
9

输出:11 22 33 44 x

# .prevent

.prevent 是阻止标签自身的默认事件,比如:a[href="#"]button[type="submit"],这些标签在冒泡结束后会执行默认事件,.stop 不会阻止默认事件。

<div @click="log(1)" @click.capture="log(11)" style="background-color: #00b0ff;padding: 10px">
  <div @click="log(2)" @click.capture="log(22)" style="background-color: #0bb69f;padding: 10px">
    <div @click="log(3)" @click.capture.stop="log(33)" style="background-color: #0d47a1;padding: 10px">
      <a @click="log(4)" @click.capture="log(44)" href="javascript: console.log('x')" style="color: white">
        点击
      </a>
    </div>
  </div>
</div>
1
2
3
4
5
6
7
8
9

输出:11 22 33 x

可以看到阻止了事件的传递,但是没有阻止默认事件输出 x

<div @click="log(1)" @click.capture="log(11)" style="background-color: #00b0ff;padding: 10px">
  <div @click="log(2)" @click.capture="log(22)" style="background-color: #0bb69f;padding: 10px">
    <div @click="log(3)" @click.capture="log(33)" style="background-color: #0d47a1;padding: 10px">
      <a @click="log(4)" @click.capture.prevent="log(44)" href="javascript: console.log('x')" style="color: white">
        点击
      </a>
    </div>
  </div>
</div>
1
2
3
4
5
6
7
8
9

输出:11 22 33 44 4 3 2 1

可以看到阻止了默认事件,没有输出 x

# .passive

对应 addEventListener 中的 passive (opens new window) 选项。使用 passive 改善滚屏性能。

浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用 preventDefault 函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。

就是每次事件产生,浏览器都会去查询一下是否有 preventDefault 阻止该次事件的默认动作。加上 passive 就是为了告诉浏览器,不用查询了,没用 preventDefault 阻止默认动作。减少了内核线程查询 prevent,提升滑动流畅度。

不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。

.passive 修饰符尤其能够提升移动端的性能。

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
1
2
3
4
上次更新: 10/20/2022, 4:51:57 PM