前面的话
Vue事件监听的方式貌似违背了关注点分离(separation of concern)的传统理念。实际上,所有的Vue.js事件处理方法和表达式都严格绑定在当前视图的ViewModel上,它不会导致维护上的困难。使用v-on
有以下好处:
1、扫一眼HTML模板便能轻松定位在JS代码里对应的方法
2、无须在JS里手动绑定事件,ViewModel代码可以是非常纯粹的逻辑,和DOM完全解耦,更易于测试
3、当一个ViewModel被销毁时,所有的事件处理器都会自动被删除。无须担心如何自己清理它们
本文将详细介绍Vue事件处理
事件监听
通过v-on
指令来绑定事件监听器
<div id="example"> <button v-on:click="counter += 1">增加 1</button> <p>这个按钮被点击了 {{ counter }} 次。</p> </div>
<script> var example = new Vue({ el: '#example', data: { counter: 0 } }) </script>
【方法】
许多事件处理的逻辑都很复杂,所以直接把JS代码写在 v-on
指令中有时并不可行。v-on
指令可以接收一个定义的方法来调用
[注意]不应该使用箭头函数来定义methods函数,因为箭头函数绑定了父级作用域的上下文,所以this将不会按照期望指向 Vue 实例
<div id="example"> <button v-on:click="num">测试按钮</button> <p>{{message}}</p> </div>
<script> var example = new Vue({ el: '#example', data:{ counter:0, message:'' }, methods: { num: function (event) { if (event) { this.message = event.target.innerHTML + '被按下' + ++this.counter + '次'; } } } }) </script>
【内联语句】
除了直接绑定到一个方法,也可以用内联JS语句
<div id="example"> <button v-on:click="say('hi')">Say hi</button> <button v-on:click="say('what')">Say what</button> <p>{{message}}</p> </div>
<script> var example = new Vue({ el: '#example', data:{ message:'' }, methods: { say: function (message) {this.message = message;} } }) </script>
有时也需要在内联语句处理器中访问原生 DOM 事件。可以用特殊变量 $event
把它传入方法
<div id="example"> <button v-on:click="say('hi',$event)">Say hi</button> <button v-on:click="say('what',$event)">Say what</button> <p>{{message}}</p> </div>
<script> var example = new Vue({ el: '#example', data:{ message:'' }, methods: { say: function (message,event) { if(event){ event.preventDefault(); } this.message = message; } } }) </script>
事件修饰符
在事件处理程序中调用event.preventDefault()
或event.stopPropagation()
是非常常见的需求。尽管可以在methods中轻松实现这点,但更好的方式:methods只有纯粹的数据逻辑,而不是去处理 DOM 事件细节
为了解决这个问题, Vue.js 为v-on
提供了事件修饰符。通过由点(.)表示的指令后缀来调用修饰符
.stop 阻止冒泡
.prevent 阻止默认事件
.capture 使用事件捕获模式
.self 只在当前元素本身触发
.once 只触发一次
下面是一些例子
<!-- 阻止单击事件冒泡 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(比如不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> <!-- 点击事件将只会触发一次 --> <a v-on:click.once="doThis"></a>
[注意]使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 @click.prevent.self
会阻止所有的点击,而 @click.self.prevent
只会阻止元素上的点击
【stop】
阻止冒泡
<div id="example" @click="setVal1" style="border:1px solid black;300px;"> <button @click="setVal">普通按钮</button> <button @click.stop="setVal">阻止冒泡</button> <button @click="reset">还原</button> <div>{{result}}</div> </div>
<script>var example = new Vue({ el: '#example', data:{ result:'' }, methods:{ setVal(event){ this.result+=' 子级 '; }, setVal1(){ this.result+=' 父级 '; }, reset(){ history.go() } } }) </script>
【prevent】
取消默认事件
<div id="example"> <a href="http://cnblogs.com" target="_blank">普通链接</a> <a @click.prevent href="http://cnblogs.com" target="_blank">取消默认行为</a> </div>
<script> var example = new Vue({ el: '#example' }) </script>
【capture】
事件捕获模式
<div id="example" @click.capture="setVal1" style="border:1px solid black;300px;"> <button @click.capture="setVal">事件捕获</button> <button @click="reset">还原</button> <div>{{result}}</div> </div>
<script>var example = new Vue({ el: '#example', data:{ result:'' }, methods:{ setVal(event){ this.result+=' 子级 '; }, setVal1(){ this.result+=' 父级 '; }, reset(){ history.go() } } }) </script>
【self】
<div id="example"> <div @click="setVal" :style="styleObj1"> <div :style="styleObj2">普通</div> <button @click="reset">还原</button> </div> <div @click.self="setVal" :style="styleObj1"> <div :style="styleObj2">self</div> <button @click="reset">还原</button> </div> </div>
<script> var styleObj1 = { display:'inline-block', height:'60px', '120px', 'background-color': 'lightblue' }; var styleObj2 = { display:'inline-block', height:'30px', '60px', 'background-color': 'lightgreen' }; var example = new Vue({ el: '#example', data:{ styleObj1:styleObj1, styleObj2:styleObj2 }, methods:{ setVal(event){ event.target.style.outline="solid" }, reset(){ history.go() } } }) </script>
【once】
只触发一次
<div id="example"> <button @click="setVal">普通按钮</button> <button @click.once="setVal">触发一次</button> <button @click="reset">还原</button> <div>{{result}}</div> </div>
<script> var example = new Vue({ el: '#example', data:{ result:'' }, methods:{ setVal(event){ this.result+=' 内容 '; }, reset(){ history.go() } } }) </script>
鼠标修饰符
这些修饰符会限制处理程序监听特定的滑鼠按键
.left 左键
.right 右键
.middle 滚轮
<div id="example"> <button @mouseup.right="right" @mouseup.middle="middle" @mouseup.left="left">{{message}}</button> </div>
<script> var example = new Vue({ el: '#example', data:{ message:'分别用左、中、右键进行点击,会出现不同的效果' }, methods:{ left(){ this.message = 'left' }, right(){ this.message = 'right' }, middle(){ this.message = 'middle' }, } }) </script>
键值修饰符
在监听键盘事件时,经常需要监测常见的键值。 Vue 允许为 v-on
在监听键盘事件时添加关键修饰符
<!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13="submit">
记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:
.enter 回车
.tab 制表键
.delete (捕获 “删除” 和 “退格” 键)
.esc 返回
.space 空格
.up 上
.down 下
.left 左
.right 右
<div id="example"> <button @keyup.enter="enter" @keyup.tab="tab" @keyup.delete="delete1" @keyup.esc="esc" @keyup.space="space" @keyup.up="up" @keyup.down="down" @keyup.left="left" @keyup.right="right">{{message}}</button> </div>
<script> var example = new Vue({ el: '#example', data:{ message:'将光标置于按钮上后,按下键盘上不同的按键,会有不同的效果' }, methods:{ enter(){ this.message = 'enter' }, tab(){ this.message = 'tab' }, delete1(){ this.message = 'delete' }, esc(){ this.message = 'esc' }, space(){ this.message = 'space' }, up(){ this.message = 'up' }, down(){ this.message = 'down' }, left(){ this.message = 'left' }, right(){ this.message = 'right' }, } }) </script>
可以通过全局 config.keyCodes
对象自定义键值修饰符别名
// 可以使用 v-on:keyup.a
Vue.config.keyCodes.a = 65
<div id="example"> <button @keyup.a="a" @keyup.b="b">{{message}}</button> </div>
<script> Vue.config.keyCodes.a = 65; Vue.config.keyCodes.b = 66; var example = new Vue({ el: '#example', data:{ message:'按下键盘上的a键或b键' }, methods:{ a(){ this.message = 'a' }, b(){ this.message = 'b' }, } }) </script>
修饰键
可以用如下修饰符开启鼠标或键盘事件监听,使在按键按下时发生响应
.ctrl
.alt
.shift
.meta
<!-- Alt + C --> <input @keyup.alt.67="clear"> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div>
下面一个例子
<div id="example"> <button @click.ctrl="ctrl" @click.alt="alt" @click.shift="shift" @click.meta="meta">{{message}}</button> </div>
<script> var example = new Vue({ el: '#example', data:{ message:'分别用按住辅助键ctrl、alt、shift、meta进行点击,会出现不同的效果' }, methods:{ ctrl(){ this.message = 'ctrl' }, alt(){ this.message = 'alt' }, shift(){ this.message = 'shift' }, meta(){ this.message = 'meta' }, } }) </script>