首页 > 编程笔记 > JavaScript笔记
阅读:58
Vue事件修饰符详解
Vue 可以对事件添加一些通用的限制,例如添加阻止事件冒泡,Vue 对这种事件的限制提供了特定的写法,称之为修饰符。
Vue 事件修饰符的语法如下:
Vue 事件修饰符处理了许多 DOM 事件的细节,让我们不再需要花费大量的时间去处理这些烦恼的事情,而将更多的精力用于程序的逻辑处理。
在 Vue 中,事件修饰符主要有:
下面分别来看一下每个修饰符的用法。
在下面的示例中,创建一个 div 元素,在其内部也创建一个 div 元素,并分别为它们添加单击事件。根据事件的冒泡机制可以得知,当单击内部的 div 元素之后,会扩散到父元素 div,从而触发父元素的单击事件。
在 Chrome 浏览器中运行程序,单击内部(inside)元素,触发自身事件,效果如下图所示。

图 1 触发内部元素事件
根据事件的冒泡机制,也会触发外部(outside)元素,效果如下图所示。

图 2 触发外部元素事件
使用 stop 修饰符阻止事件冒泡。修改上面 HTML 对应的代码:
在 Chrome 浏览器中运行程序,单击内部的 div 后,将不再触发父元素单击事件,如下图所示。

图 3 只触发内部元素事件
在下面的示例中,创建了 3 个 div 元素,把它们分别嵌套,并添加单击事件。为外层的两个 div 元素添加 capture 修饰符,当单击内部的 div 元素时,将从外向内触发含有 capture 修饰符的 div 元素的事件。
在 Chrome 浏览器中运行程序,单击内部的 div 元素,会先触发添加了 capture 修饰符的外层 div 元素,然后触发中间 div 元素,最后触发单击的内部元素。
self 修饰符会监视事件是否直接作用在元素上,若不是,则冒泡跳过该元素。
例如:
在 Chrome 浏览器中运行程序,单击内部的 div 后,触发该元素的单击事件。由于中间 div 添加了 self 修饰符,因此直接单击该元素就会跳过,内部 div 执行完毕后,外层的 div 紧接着执行。
不像其他只能对原生的 DOM 事件起作用的修饰符,once 修饰符还能被用到自定义的组件事件上。
例如:
在 Chrome 浏览器中运行程序,单击“点赞0”按钮,count 值从 0 变成 1,之后,无论再单击多少次,count 的值仍然是 1,效果如下图所示。

图 4 once修饰符作用效果
注意,不要把 passive 和 prevent 修饰符一起使用,因为 prevent 将会被忽略,同时浏览器可能会展示一个警告。passive 修饰符会告诉浏览器不想阻止事件的默认行为。
例如:
在 Chrome 浏览器中运行程序,单击“阻止跳转”链接,触发 alert() 事件弹出“阻止 <a> 标签的链接”,效果如下图所示;然后单击“确定”按钮,可以发现页面将不再进行跳转。

图 5 prevent修饰符
通俗地说,就是每次事件产生时,浏览器都会去查询一下是否有 preventDefault 阻止该次事件的默认动作,加上 passive 修饰符就是为了告诉浏览器,不用查询了,没有 preventDefault 阻止默认行为。
passive 修饰符一般用在滚动监听、@scoll 和 @touchmove 中。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询 prevent 会使滑动卡顿,通过 passive 修饰符将内核线程查询跳过,可以大大提升滑动的流畅度。
注意,使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生。因此,使用 v-on:click.prevent.self 会阻止所有的单击,而 v-on:click.self.prevent 只会阻止对元素自身的单击。
Vue 事件修饰符的语法如下:
v-on:事件.修饰符在事件处理程序中,调用 event.preventDefault()(阻止默认行为)或 event.stopPropagation()(阻止事件冒泡)是非常常见的需求。尽管可以在方法中轻松实现这一点,但更好的方式是使用纯粹的数据逻辑,而不是去处理 DOM 事件细节。
Vue 事件修饰符处理了许多 DOM 事件的细节,让我们不再需要花费大量的时间去处理这些烦恼的事情,而将更多的精力用于程序的逻辑处理。
在 Vue 中,事件修饰符主要有:
- stop:等同于 JavaScript 中的 event.stopPropagation(),阻止事件冒泡。
- capture:与事件冒泡的方向相反,事件捕获由外到内。
- self:只会触发自己范围内的事件。
- once:只会触发一次。
- prevent:等同于 JavaScript 中的 event.preventDefault(),阻止默认事件的发生。
- passive:执行默认行为。
下面分别来看一下每个修饰符的用法。
stop事件修饰符
stop 修饰符用来阻止事件冒泡。在下面的示例中,创建一个 div 元素,在其内部也创建一个 div 元素,并分别为它们添加单击事件。根据事件的冒泡机制可以得知,当单击内部的 div 元素之后,会扩散到父元素 div,从而触发父元素的单击事件。
- <head>
- <meta charset="UTF-8">
- <title>冒泡事件</title>
- <style>
- .outside{
- width: 200px;
- height: 100px;
- border: 1px solid red;
- text-align: center;
- }
- .inside{
- width: 100px;
- height: 50px;
- border:1px solid black;
- margin:15% 25%;
- }
- </style>
- </head>
- <body>
- <div id="app">
- <div class="outside" @click="outside">
- <div class="inside" @click ="inside">冒泡事件</div>
- </div>
- </div>
- <!--引入Vue文件-->
- <script src="https://unpkg.com/vue@next"></script>
- <script>
- //创建一个应用程序实例
- const vm= Vue.createApp({
- methods: {
- outside: function () {
- alert("外面div的单击事件")
- },
- inside: function () {
- alert("内部div的单击事件")
- }
- }
- //在指定的DOM元素上装载应用程序实例的根组件
- }).mount('#app');
- </script>

图 1 触发内部元素事件
根据事件的冒泡机制,也会触发外部(outside)元素,效果如下图所示。

图 2 触发外部元素事件
使用 stop 修饰符阻止事件冒泡。修改上面 HTML 对应的代码:
- <div id="app">
- <div class="outside" @click="outside">
- <div class="inside" @click.stop="inside">阻止事件冒泡</div>
- </div>
- </div>

图 3 只触发内部元素事件
capture事件修饰符
事件捕获模式与事件冒泡模式是一对相反的事件处理流程,当想要将页面元素的事件流改为事件捕获模式时,只需要在父级元素的事件上使用 capture 修饰符即可。若有多个该修饰符,则由外而内触发。在下面的示例中,创建了 3 个 div 元素,把它们分别嵌套,并添加单击事件。为外层的两个 div 元素添加 capture 修饰符,当单击内部的 div 元素时,将从外向内触发含有 capture 修饰符的 div 元素的事件。
- <style>
- .outside{
- width: 300px;
- height: 180px;
- color:white;
- font-size: 30px;
- background: red;
- margin-top: 120px;
- }
- .center{
- width: 200px;
- height: 120px;
- background: #17a2b8;
- }
- .inside{
- width: 100px;
- height: 60px;
- background: #a9b4ba;
- }
- </style>
- <div id="app">
- <div class="outside" @click.capture="outside">
- <div class="center" @click.capture="center">
- <div class="inside" @click="inside">内部</div>
- 中间
- </div>
- 外层
- </div>
- </div>
- <!--引入Vue文件-->
- <script src="https://unpkg.com/vue@next"></script>
- <script>
- //创建一个应用程序实例
- const vm= Vue.createApp({
- methods: {
- outside:function(){
- alert("外面的div")
- },
- center:function(){
- alert("中间的div")
- },
- inside: function () {
- alert("内部的div")
- }
- }
- //在指定的DOM元素上装载应用程序实例的根组件
- }).mount('#app');
- </script>
self事件修饰符
self 修饰符可以理解为跳过冒泡事件和捕获事件,只有直接作用在该元素上的事件才可以执行。self 修饰符会监视事件是否直接作用在元素上,若不是,则冒泡跳过该元素。
例如:
- <style>
- .outside{
- width: 300px;
- height: 180px;
- color:white;
- font-size: 30px;
- background: red;
- margin-top: 100px;
- }
- .center{
- width: 200px;
- height: 120px;
- background: #17a2b8;
- }
- .inside{
- width: 100px;
- height: 60px;
- background: #a9b4ba;
- }
- </style>
- <div id="app">
- <div class="outside" @click="outside">
- <div class="center" @click.self="center">
- <div class="inside" @click="inside">内部</div>
- 中间
- </div>
- 外层
- </div>
- </div>
- <!--引入Vue文件-->
- <script src="https://unpkg.com/vue@next"></script>
- <script>
- //创建一个应用程序实例
- const vm= Vue.createApp({
- methods: {
- outside: function () {
- alert("外面的div")
- },
- center: function () {
- alert("中间的div")
- },
- inside: function () {
- alert("内部的div")
- }
- }
- //在指定的DOM元素上装载应用程序实例的根组件
- }).mount('#app');
- </script>
once事件修饰符
有时需要只执行一次的操作,比如微信朋友圈点赞,便可以使用 once 修饰符来完成。不像其他只能对原生的 DOM 事件起作用的修饰符,once 修饰符还能被用到自定义的组件事件上。
例如:
- <div id="app">
- <button @click.once="add">点赞 {{num }}</button>
- </div>
- <!--引入Vue文件-->
- <script src="https://unpkg.com/vue@next"></script>
- <script>
- //创建一个应用程序实例
- const vm= Vue.createApp({
- //该函数返回数据对象
- data(){
- return{
- num:0
- }
- },
- methods:{
- add:function(){
- this.num +=1
- },
- }
- //在指定的DOM元素上装载应用程序实例的根组件
- }).mount('#app');
- </script>

图 4 once修饰符作用效果
prevent事件修饰符
prevent 修饰符用于阻止默认行为,例如 <a> 标签,当单击标签时,默认行为会跳转到对应的链接,如果在 <a> 标签上添加 prevent 修饰符,则不会跳转到对应的链接。注意,不要把 passive 和 prevent 修饰符一起使用,因为 prevent 将会被忽略,同时浏览器可能会展示一个警告。passive 修饰符会告诉浏览器不想阻止事件的默认行为。
例如:
- <div id="app">
- <div style="margin-top: 100px">
- <a @click.prevent="alert()" href="https://cn.vuejs.org" >阻止跳转</a>
- </div>
- </div>
- <!--引入Vue文件-->
- <script src="https://unpkg.com/vue@next"></script>
- <script>
- //创建一个应用程序实例
- const vm= Vue.createApp({
- methods:{
- alert:function(){
- alert("阻止<a>标签的链接")
- }
- }
- //在指定的DOM元素上装载应用程序实例的根组件
- }).mount('#app');
- </script>

图 5 prevent修饰符
passive事件修饰符
明明是默认执行的行为,为什么还要使用 passive 修饰符呢?原因是浏览器只有等内核线程执行到事件监听器对应的 JavaScript 代码时,才能知道内部是否会调用 preventDefault 函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。在这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。通俗地说,就是每次事件产生时,浏览器都会去查询一下是否有 preventDefault 阻止该次事件的默认动作,加上 passive 修饰符就是为了告诉浏览器,不用查询了,没有 preventDefault 阻止默认行为。
passive 修饰符一般用在滚动监听、@scoll 和 @touchmove 中。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询 prevent 会使滑动卡顿,通过 passive 修饰符将内核线程查询跳过,可以大大提升滑动的流畅度。
注意,使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生。因此,使用 v-on:click.prevent.self 会阻止所有的单击,而 v-on:click.self.prevent 只会阻止对元素自身的单击。