在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点 但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。
prevent 修饰符【常用】
prevent 修饰符用于阻止默认事件。与 event.preventDefault() 效果相同。
阻止默认事件:某些标签带有默认的事件,例如 a 标签默认跳转页面、submit 属性默认提交并刷新页面。如果不想触发这些默认的事件,就需要阻止默认事件了。
<div id="APP"> <a href="http://www.baidu.com" @click.prevent="info">百度一下</a> </div>
const vm = new Vue({ el: "#APP", methods:{ info(){ console.log("显示信息"); }, }, });
注:如果没有 prevent 修饰符,点击后会跳转到百度。而现在点击后不会跳转页面。
stop 修饰符【常用】:
stop 修饰符用于阻止事件冒泡。与 event.stopPropagation() 效果相同。
阻止事件冒泡:当一个元素执行某个事件的时候,这个事件会一直向上传播,如果它的父元素也有相同的事件,也会被触发执行。如果不想让事件向上传播,就需要阻止事件冒泡了。
<div id="APP"> <div @click="info1"> <p @click.stop="info2">阻止事件冒泡</p> </div> </div>
const vm = new Vue({ el: "#APP", methods:{ info1(){ console.log("我是DIV标签"); }, info2(){ console.log("我是P标签"); }, }, });
注:如果没有 stop 修饰符,点击后两个事件都会触发。而现在只有 info2 触发执行了。
once 修饰符【常用】:
once 修饰符用于只让事件触发一次。
<div id="APP"> <button @click.once="info">只会触发一次</button> </div>
const vm = new Vue({ el: "#APP", methods:{ info(){ console.log("我只出来一次哦"); }, }, });
注:只有第一次点击按钮会触发事件,事件只执行一次。
capture 修饰符:用于让事件以捕获模式触发。
.box{ width: 100px; height: 100px; padding: 20px; background-color: aqua; } .box p{ width: 60px; height: 60px; background-color: red; }
<div id="APP"> <div class="box" @click.capture="info1"> 我是div标签 <p @click="info2">我是p标签</p> </div> </div>
const vm = new Vue({ el: "#APP", methods:{ info1(){ console.log("外"); }, info2(){ console.log("内"); }, }, });
注:如果没有 capture 修饰符,事件默认冒泡阶段触发,会先执行内,后执行外。而现在 info1 事件在捕获阶段触发,会先执行外,后执行内。
self 修饰符:用于指定事件不会被事件冒泡或事件捕获触发,只有操作当前元素才会触发。
<div id="APP"> <div class="box" @click.self="info"> 内容 <button @click="info">按钮</button> </div> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ console.log(e.target); }, }, });
注:如果没有 self 修饰符,点击按钮时,事件会向上传播,导致 div 上的事件也会被触发。而现在点击按钮不会触发 div 上的事件,只有点击内容才能执行 div 上的事件。
passive 修饰符:常用于 scroll 事件,可以使内容立即滚动,不需要等待事件执行完毕。
.list{ width: 200px; height: 200px; background-color: aqua; overflow-y: scroll; } .list li{ height: 100px; }
<div id="APP"> <ul class="list" @scroll.passive="demo"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> </div>
const vm = new Vue({ el: "#APP", methods:{ demo(){ for(let i = 0; i < 10000; i++){ console.log(i); } console.log("执行完毕!"); }, }, });
注:推荐给 scroll 事件添加 passive 修饰符,它能够提升移动端的性能。避免等待事件执行完毕后才能触发内容滚动。
使用多个修饰符:
<div id="APP"> <a href="http://www.baidu.com" @click.prevent.once="demo">百度一下</a> </div>
const vm = new Vue({ el: "#APP", methods:{ demo(){ console.log("阻止默认事件并且只执行一次"); }, }, });
注:可以同时使用多个修饰符。当第一次点击时会执行事件并且阻止默认事件,第二次点击就会触发 a 标签跳转页面。也就是说它现在只会阻止一次默认事件。
注:使用多个修饰符时,顺序很重要。相应的代码会以同样的顺序产生。另外不要把 passive 和 prevent 一起使用,因为 prevent 将会被忽略,同时浏览器可能会向你展示一个警告。
按键修饰符:
<div id="APP"> <p>enter 修饰符</p> <input type="text" placeholder="按回车键提交内容" @keyup.enter="info"> <p>delete 修饰符</p> <input type="text" placeholder="按删除键或退格键提交内容" @keyup.delete="info"> <p>esc 修饰符</p> <input type="text" placeholder="按退出键提交内容" @keyup.esc="info"> <p>space 修饰符</p> <input type="text" placeholder="按空格键提交内容" @keyup.space="info"> <p>tab 修饰符【特殊,必须配合 keydown 去使用】</p> <input type="text" placeholder="按换行键提交内容" @keydown.tab="info"> <p>up 修饰符</p> <input type="text" placeholder="按上键提交内容" @keyup.up="info"> <p>down 修饰符</p> <input type="text" placeholder="按下键提交内容" @keyup.down="info"> <p>left 修饰符</p> <input type="text" placeholder="按左键提交内容" @keyup.left="info"> <p>right 修饰符</p> <input type="text" placeholder="按左键提交内容" @keyup.right="info"> <p>w 修饰符</p> <input type="text" placeholder="按 w 键提交内容" @keyup.w="info"> <p>......</p> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
注:大部分按键都可以使用,只有个别多单词按键需要改为短横线命名。例如:PrintScreen 按键需要改为 print-screen 才能使用(键盘上的 PrtSc 键)。
系统修饰键:
<div id="APP"> <p>ctrl 修饰符</p> <input type="text" placeholder="按ctrl键提交内容" @keydown.ctrl="info"> <p>alt 修饰符</p> <input type="text" placeholder="按alt键提交内容" @keydown.alt="info"> <p>shift 修饰符</p> <input type="text" placeholder="按shift键提交内容" @keydown.shift="info"> <p>meta 修饰符</p> <input type="text" placeholder="按系统键提交内容" @keydown.meta="info"> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
注:系统修饰键比较特殊,配合 keydown 使用可以正常触发。配合 keyup 使用时,需要在按下修饰键的同时,再按下其它键,随后释放其它键,事件才能被触发。
系统修饰键配合使用:多个按键修饰符同样可以组合使用。
<div id="APP"> <p>ctrl + a 修饰符</p> <input type="text" placeholder="按 ctrl + a 键提交内容" @keydown.ctrl.a="info"> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
按键修饰符也可以配合事件使用。
<div id="APP"> <p>ctrl + 点击 修饰符</p> <input type="text" placeholder="按住ctrl键点击提交内容" @click.ctrl="info"> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
注:现在只有按住 ctrl 键再点击输入框才能触发事件。
鼠标修饰键:
<div id="APP"> <p>left 修饰符</p> <input type="text" placeholder="点击鼠标左键提交内容" @click.left="info"> <p>right 修饰符</p> <input type="text" placeholder="点击鼠标右键提交内容" @click.right="info"> <p>middle 修饰符</p> <input type="text" placeholder="点击鼠标滚轮提交内容" @click.middle="info"> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
exact 修饰符:就是允许你控制由精确的系统修饰符组合触发的事件。
<div id="APP"> <p>按住 ctrl 键再点击触发</p> <input type="text" placeholder="ctrl + 点击" @click.ctrl="info"> <p>只能按住 ctrl 键再点击触发</p> <input type="text" placeholder="ctrl + 点击" @click.ctrl.exact="info"> </div>
const vm = new Vue({ el: "#APP", methods:{ info(e){ alert(e.target.value); }, }, });
注:添加 exact 修饰符后,只能按下指定的按键触发。如果多按或少按任意一个键,都不会执行。例如第二个输入框只能按 ctrl 键再点击,多按一个键也不会执行。
原创作者:吴小糖
创作时间:2023.3.9