一、简介
在Vue中,修饰符是一种特殊的语法,用于修改指令或事件绑定的行为,它们以点号(.
)的形式添加到指令或事件的后面,并可以改变其默认行为或添加额外的功能,如:禁止事件冒泡、数据双向绑定等,当然修饰符的功能也可以通过js
在事件函数中自行实现,但是我们更希望在函数中只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
因此Vue为我们提供了很多修饰符,相当于将一些常用DOM事件逻辑进行了封装,根据功能类别,共分为以下几类:① 事件修饰符。② 按键修饰符。③ 系统修饰符。 ④ 鼠标修饰符。 ⑤ 表单修饰符。⑥ 其他修饰符。
多个修饰符可以在同一事件上同时串联使用,多方位的限制事件的触发范围。
注意:下面的案例代码,全都是在Chrome浏览器中进行的实验。
二、事件修饰符
1、.stop
该修饰符用于实现阻止事件冒泡,其作用等同于event.stopPropagation()
。
案例代码:
<div style="width: 200px; height: 200px; background: #ccc" @click="fatherClick()">
<div style="width: 100px; height: 100px; background: red" @click.stop="sonClick()">
stop修饰符测试
</div>
</div>
<script>
fatherClick() {
console.log("父元素的点击事件被冒泡触发了");
},
sonClick() {
console.log("带有stop修饰符的子元素被点击了");
},
</script>
执行结果:
点击子元素,子元素的事件正常触发执行,但父元素事件没有被触发。
2、.prevent
该修饰符用于实现阻止事件的默认行为,其作用等同于event.preventDefault()
。
案例代码:
<a href="https://www.baidu.com" target="_blank" @click.prevent="preventClick()">测试prevent修饰符</a>
<script>
preventClick() {
console.log("阻止了默认事件行为,但事件绑定函数正常执行");
},
</script>
执行结果:
点击该元素后,页面并未发生跳转,但是click
事件正常触发和执行。
3、.capture
该修饰符用于实现修改事件的传播过程为捕获模式(正常为冒泡模式),其作用等同于在使用addEventListener('事件名','事件函数',{ capture: true })
注册事件时将第三个参数中的capture
设置为true。
**冒泡模式: **事件从触发事件的元素开始向上传播,逐级向上层父元素传递,直到达到根元素(通常是 window 对象)。这意味着父元素的事件处理程序会在子元素的事件处理程序之后被调用。
捕获模式: 事件从根元素开始向下传播,逐级向下层子元素传递,直到达到触发事件的元素。这意味着父元素的事件处理程序会在子元素的事件处理程序之前被调用。
案例代码:
<div style="width: 200px; height: 200px; background: #ccc" @click.capture="fatherClick()">
<div style="width: 100px; height: 100px; background: red" @click="sonClick()">
capture修饰符测试
</div>
</div>
<script>
fatherClick() {
console.log("父元素的点击事件被触发了");
},
sonClick() {
console.log("子元素的点击事件被触发了");
},
</script>
执行结果:
点击子元素后,先触发父元素的点击事件,然后再触发子元素的点击事件。
4、.self
该修饰符用于实现,只有当触发事件的元素与当前事件绑定的元素是同一个元素时(即event.target
与event.currentTarget
指向同一个元素),事件绑定函数才会被执行。主要可用来过滤因为事件冒泡而触发的事件。
event.currentTarget
的值只能在事件处理过程中被使用。如果尝试用 console.log()
在控制台打印 event
对象,你会发现 currentTarget
的值是 null
,如果想在控制台打印 currentTarget
,应该直接使用 console.log(event.currentTarget)
。
案例代码:
<div style="width: 200px; height: 200px; background: #ccc" @click.self="fatherClick()">
<div style="width: 100px; height: 100px; background: red" @click="sonClick()">
self修饰符测试
</div>
</div>
<script>
fatherClick() {
console.log("父元素的点击事件被触发了");
},
sonClick() {
console.log("子元素的点击事件被触发了");
},
</script>
执行结果:
点击子元素,子元素事件正常触发执行,虽然会正常冒泡到父元素,但父元素事件不会被触发执行。只有点击父元素本身时,父元素的事件才会正常触发执行。
5、.once
该修饰符于v2.1.4版本新增,用于实现限制事件只触发执行一次,执行完成后绑定的事件会自动被移除,其作用等同于在使用addEventListener('事件名','事件函数',{ once: true })
注册事件时将第三个参数中的once
设置为true。后续再次触发事件,事件并不会再次执行,但事件会正常向上冒泡。当绑定事件的元素被销毁再重绘之后,限制会重置,如果元素只是通过display: none;
进行隐藏,则不会重置限制。
该修饰符不仅可以用于原生DOM事件,也可用于父子组件之间的自定义组件事件。
案例代码:
<div style="width: 200px; height: 200px; background: #ccc" @click="fatherClick()">
<div style="width: 100px; height: 100px; background: red" @click.once="sonClick()">
once修饰符测试
</div>
</div>
<script>
fatherClick() {
console.log("父元素的点击事件被触发了");
},
sonClick() {
console.log("子元素的点击事件被触发了");
},
</script>
执行结果:
第一次点击子元素,子元素绑定事件正常执行,然后冒泡到父元素,父元素事件也正常执行。后续再点击子元素,子元素事件不再被触发执行,但会正常后冒泡到父元素,触发父元素事件执行。
6、.passive
该修饰符于v2.3.0版本新增,用于告诉浏览器当前事件永远不会调用 preventDefault()
来阻止默认行为,其作用等同于在使用addEventListener('事件名','事件函数',{ passive: true })
注册事件时将第三个参数中的passive
设置为true。并且在事件被触发时,无需等待绑定事件执行,立即执行事件的默认行为。通常用于提升移动端的滚屏性能。
不要把 .passive
和 .prevent
一起使用,因为 .prevent
将会被忽略,同时浏览器可能会向你展示一个警告,因为.passive
的目的就是告诉浏览器你不想阻止事件的默认行为。
根据规范,事件的 passive
默认值始终为 false
。然而,这增加了移动端触摸事件和滚轮事件的事件监听器在浏览器尝试滚动页面时阻塞浏览器主线程的可能性——这可能会大大降低浏览器处理页面滚动时的性能。为了避免这一问题,大部分浏览器(Safari 和 IE 除外)将文档级节点 Window
、Document
和 Document.body
上的 wheel
、mousewheel
、touchstart
和 touchmove
事件的 passive
默认值更改为 true
。如此,事件监听器便不能取消事件,也不会在用户滚动页面时阻止页面呈现。
案例代码:
<div @scroll.passive="onScroll()">...</div>
执行结果:
滚动事件的默认行为 (即滚动行为) 将会立即触发,而不会等待事件绑定的onScroll()
函数执行结束后再触发。
三、按键修饰符
按键修饰符是Vue提供的处理键盘事件的特殊方式。它允许你在处理键盘事件时,对触发事件的按键进行限制。使用按键修饰符之后,只有修饰符对应的键盘按键才会触发对应事件。
该类型的修饰符通常只在文本域元素上使用,但并不绝对,我们也可以在任何一个非文本域元素上,通过增加tabindex=0
属性的方式,使元素可聚焦,从而可以使用该类型的修饰符。
1、.enter
该修饰符对应键盘中的Enter
回车键,限制触发事件的按键只能是Enter
回车键。
案例代码:
<!-- 通过在非文本域元素中增加tabindex="0"属性 使其能够使用按键修饰符 -->
<div tabindex="0" @keyup.enter="ajFunction($event)">按键修饰符</div>
执行结果:
鼠标指针点击该元素后,再按下键盘的Enter
回车键,页面上该元素会出现聚焦效果,并且会触发对应的按键事件。
2、.tab
该修饰符对应键盘中的tab
键,限制触发事件的按键只能是tab
键。
案例代码:
<input @keyup.tab="ajFunction($event, 2)" placeholder="按键修饰符" />
执行结果:
按下键盘的tab
键,如果焦点聚焦到该元素,则会触发对应的按键事件。如果按下tab
键之前,目标元素正处于聚焦状态,则焦点会切换到下一可聚焦的元素,当前元素的按键事件也不会触发。
3、.delete
该修饰符对应键盘中的delete
删除键和Backspace
删除键,限制触发事件的按键只能是delete
删除键Backspace
删除键。
案例代码:
<input @keyup.delete="ajFunction($event, 2)" placeholder="按键修饰符" />
执行结果:
4、.esc
该修饰符对应键盘中的esc
退出键,限制触发事件的按键只能是esc
退出键。
案例代码:
<input @keyup.esc="ajFunction($event, 2)" placeholder="按键修饰符" />
执行结果:
5、.space
该修饰符对应键盘中的space
空格键,限制触发事件的按键只能是space
空格键。
案例代码:
<input @keyup.space="ajFunction($event, 2)" placeholder="按键修饰符" />
执行结果:
6、.up/.down/.left/.right
这四个按键修饰对应着键盘上的上下左右四个键位,设置对应的修饰符可以限制触发事件的按键。
案例代码:
<input @keyup.up="ajFunction($event, 2)" placeholder="按键修饰符1" />
<input @keyup.down="ajFunction($event, 2)" placeholder="按键修饰符2" />
<input @keyup.left="ajFunction($event, 2)" placeholder="按键修饰符3" />
<input @keyup.right="ajFunction($event, 2)" placeholder="按键修饰符4" />
执行结果:
7、按键名和按键码
除了使用Vue提供的按键修饰符之外,我们还可以通过按键名(KeyboardEvent.key转换为 kebab-case 来作为修饰符)和按键码(keyCode直接作为修饰符),两种方式来实现限制触发事件的按键。
注意:keyCode
的事件用法已经被废弃了并可能不会被最新的浏览器支持。
案例代码:
<input @keyup.arrow-up="ajFunction($event, 2)" placeholder="按键修饰符2" />
执行结果:
四、系统修饰符
系统修饰符是用来进一步限制鼠标或键盘事件的触发范围,只有在按下系统修饰符对应按键的同时,再去操作其他按键,才能触发对应的鼠标或按键事件,如果单独只按下系统修饰符对应按键或者只按下其他按键都不会触发鼠标或按键事件。
例如在和 keyup
事件一起用时,事件触发时修饰键必须处于按下状态。以.ctrl
修饰符为例,只有在按住 ctrl
的情况下释放其它按键,才能触发 keyup.ctrl
。而单单释放 ctrl
或者单独释放其他按键都不会触发事件。
1、.ctrl
该修饰符用于进一步限制按键事件,必须得在按下ctrl
键位的同时操作其他按键才会触发对应事件。
但修饰符在浏览器中不能与鼠标事件合用,因为浏览器系统定义很多关于ctrl
的快捷键,可能会造成逻辑冲突。
案例代码:
<!-- 在按下ctrl的同时 松开其他任意一个按键 才会触发事件 -->
<input @keyup.ctrl="ajFunction($event, 2)" placeholder="按键修饰符1" />
<!-- 在按下ctrl的同时 松开上方向键按键 才会触发事件 -->
<input @keyup.ctrl.up="ajFunction($event, 2)" placeholder="按键修饰符1" />
执行结果:
2、.alt
该修饰符用于进一步限制按键事件,必须得在按下alt
键位的同时操作其他按键才会触发对应事件。
该修饰符可以与鼠标事件合用。
但是经过实践发现,该修饰符不能跟.space
、.tab
等部分修饰符合用,目前原因未知,怀疑是与浏览器快捷键冲突了。
案例代码:
<!-- 在按下alt的同时 用鼠标点击事件 才会触发事件 -->
<div @click.alt="ajFunction($event, 1)">系统修饰符</div>
<!-- 在按下alt的同时 松开其他任意一个按键 才会触发事件 -->
<input @keyup.alt="ajFunction($event, 2)" placeholder="按键修饰符1" />
<!-- 在按下alt的同时 松开删除按键 才会触发事件 -->
<input @keyup.alt.delete="ajFunction($event, 2)" placeholder="按键修饰符1" />
执行结果:
3、.shift
该修饰符用于进一步限制按键事件,必须得在按下shift
键位的同时操作其他按键才会触发对应事件。
该修饰符可以与鼠标事件合用。
案例代码:
<!-- 在按下shift的同时 用鼠标点击事件 才会触发事件 -->
<div @click.shift="ajFunction($event, 1)">系统修饰符</div>
<!-- 在按下shift的同时 松开其他任意一个按键 才会触发事件 -->
<input @keyup.shift="ajFunction($event, 2)" placeholder="系统修饰符1" />
<!-- 在按下shift的同时 松开空格按键 才会触发事件 -->
<input @keyup.shift.space="ajFunction($event, 2)" placeholder="系统修饰符1" />
执行结果:
4、.meta
该修饰符用于进一步限制按键事件,但是该修饰符比较特殊,在不同系统对应的按键不同。在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。
该修饰符可以与鼠标事件合用,但不能跟键盘按键合用,原因未知,怀疑是与浏览器快捷键冲突了。
案例代码:
<!-- 在按下meta的同时 用鼠标点击事件 才会触发事件 -->
<div @click.meta="ajFunction($event, 1)">系统修饰符</div>
执行结果:
5、.exact
该修饰符是在 v2.5.0 版本中新增的修饰符,用于更精准的控制系统修饰符组合触发的事件。
案例代码:
<!-- 单独使用系统修饰符alt 表示只要按下的按键中包含alt键 就可以通过鼠标触发事件 同时按下了其他按键并不影响 -->
<div @click.alt="ajFunction($event, 1)">系统修饰符1</div>
<!-- 使用系统修饰符alt+exact 表示按下的按键中只能包含alt键 不可以有其他按键 然后才能通过鼠标触发事件
如果同时按下了其他按键 则不会触发事件 -->
<div @click.alt.exact="ajFunction($event, 1)">系统修饰符2</div>
<!-- 单独使用系统修饰符exact 表示通过鼠标触发事件时,不能按下任何一个系统修饰符对应的按键 才能触发事件
否则事件不会被触发-->
<div @click.exact="ajFunction($event, 1)">系统修饰符3</div>
执行结果:
五、鼠标按钮修饰符
鼠标修饰符用来限制触发鼠标事件的按键,共分为三种:left
-鼠标左键、right
-鼠标右键、middle
-鼠标中键(鼠标滚轮)。
1、.left
该修饰限制只当点击鼠标左键时,才会触发对应的鼠标事件。
2、.right
该修饰限制只当点击鼠标右键时,才会触发对应的鼠标事件。但是在网页中点击鼠标右键是会显示页面功能菜单的,可以借助.prevent
取消默认行为来屏蔽显示菜单功能。
3、.middle
该修饰限制只当点击鼠标中键(鼠标滚轮)时,才会触发对应的鼠标事件。
案例代码:
<div @click.left="ajFunction($event, 1)">鼠标修饰符1</div>
<div @click.right="ajFunction($event, 2)">鼠标修饰符2</div>
<div @click.middle="ajFunction($event, 3)">鼠标修饰符3</div>
执行结果:
六、表单修饰符
该类型的修饰符基本都是在文本域元素上与v-model
语法糖一起使用,用于在处理表单输入时修改或增强默认行为。下面所有讲解中的文本域元素都以input
元素为示例。
1、.lazy
默认情况下,使用v-model
在文本域元素上实现数据的双向绑定时,都是在input
事件后更新数据(IME拼字阶段的状态例外,详情请看第二段)。我们可以通过使用该修饰符,修改更新数据的时机为每次 change
事件后。
对于需要使用 IME 的语言 (中文,日文和韩文等),你会发现 v-model
不会在 IME 输入还在拼字阶段时触发更新。如果你的确想在拼字阶段也触发更新,请直接使用自己的 input
事件监听器和 value
绑定而不要使用 v-model
。
案例代码:
<input v-model="msg" @input="inputHandle" @change="changeHandle" placeholder="表单修饰符1" />
<input v-model.lazy="msg" @input="inputHandle" @change="changeHandle" placeholder="表单修饰符2" />
<script>
inputHandle() {
console.log("input事件被触发了---", this.msg);
},
changeHandle() {
console.log("change事件被触发了--", this.msg);
},
</script>
页面表现:
2、.number
该修饰符的作用是将用户输入的内容自动转化成Number
数字类型,其内部是通过parseFloat()
方法进行处理,如果输入的内容不能被该方法处理,那将返回原始输入的内容值。如果一开始输入的内容可以被转成数字(如:123
),但是后续输入的内容无法转成数字(如:123abc
),则在change
事件触发后,后面输入的非数字内容将会被清空,变量值最终为123
。并且在input事件阶段获取到的变量值也为123
,不包含后面输入的非数字内容。
如果设置了input
元素的type="number"
,则会自动启用该修饰符。
案例代码:
<input v-model.number="msg" @input="inputHandle" @change="changeHandle" placeholder="表单修饰符1" />
执行结果:
先输入123
,然后清空,再输入abc
,然后清空,最后输入123
,紧接着输入abc
,然后切换焦点,触发change
事件
3、.trim
该修饰符的作用是自动去除输入内容前后两端的空格。在input
事件触发时,就已经将空格去除。
案例代码:
<input v-model.trim="msg" @input="inputHandle" @change="changeHandle" placeholder="表单修饰符1" />
<script>
inputHandle() {
console.log("input事件被触发了---",this.msg,"--数据长度--",this.msg.length);
},
changeHandle() {
console.log("change事件被触发了--",this.msg,"--数据长度--",this.msg.length);
},
</script>
页面效果:
七、其他修饰符
1、.sync
该修饰符用于实现父子组件之间props
传递数据的双向绑定。在父组件向子组件传值时,使用该修饰符后,我们就可以直接在子组件中通过$emit('update:propName')
来更新数据。
案例代码:
父组件:
<template>
<div>
<h1>这是父组件{{ count }}</h1>
<!-- 向子组件传递数据并使用sync修饰符 -->
<son :count.sync="count"></son>
</div>
</template>
<script>
import son from "../components/son.vue";
export default {
components: {
son,
},
data() {
return {
count: 1,
};
},
};
</script>
子组件:
<template>
<div>
<h3 @click="add()">这是子组件{{ count }}</h3>
</div>
</template>
<script>
export default {
props: {
// 接收父组件传递过来的值
count: {
type: Number,
default: 0,
},
},
methods: {
add() {
// 子组件直接修改父组件传递的值
this.$emit("update:count", this.count + 1);
},
},
};
</script>
页面效果:
初始状态:
点击后:
八、修饰符串联
在同一个元素上,修饰符并不是只能使用一种,而是能够叠加使用多个修饰符,其作用也将同事发挥作用,对事件作更详细的限制。 但要注意修饰符的使用顺序,对于大部分修饰符来说,顺序并不重要。但对于部分修饰符来说顺序很重要,以 .prevent
和 .self
这两个修饰符来说,顺序会影响它们的行为。因为这两个修饰符的作用顺序与使用顺序相同,后面的修饰符是在前面修饰符的基础上进一步做限制。
例如:用 @click.prevent.self
会阻止当前元素的所有的点击产生的默认行为,包括冒泡过来的点击事件,而 @click.self.prevent
只会阻止当前元素自身点击产生的默认行为,冒泡过来的点击则会正常执行默认行为。
常见组合修饰符:
1、.stop.prevent
在阻止事件冒泡的同时,阻止事件默认行为。
2、.enter.space
限制触发事件的按键只能为Enter
键或者 Space
键。
3、.self.once
只有当事件是从元素本身触发时执行绑定函数,且只触发一次。
4、.prevent.self
阻止当前元素的当前事件的产生的默认行为,包括冒泡过来的事件。
5、.lazy.trim.number
当离开输入框时(change
事件),移除首尾空白后的输入框的值,将转为数值类型,然后进行数据同步。
6、其他。。。
九、相关资料
Vue官方文档-事件修饰符