监听事件
我们可以使用v-on监听dom事件,执行对应的js代码,
可以使用v-on:click='methodName'或@click="methodName"
二者等价,后者是前者的语法糖
Vue.createApp({
data() {
return {
counter: 0
}
}
}).mount('#basic-event')
<div id="basic-event">
<button @click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
事件处理方法
之前我们简单调用了一小段js代码,可以调用对应的methods来执行更复杂的操作
Vue.createApp({
data() {
return {
name: 'Vue.js'
}
},
methods: {
greet(event) {
// `methods` 内部的 `this` 指向当前活动实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM event
if (event) {
alert(event.target.tagName)
}
}
}
}).mount('#event-with-method')
<div id="event-with-method">
<!-- `greet` 是在下面定义的方法名 -->
<button @click="greet">Greet</button>
</div>
我们也可以传入一些参数
如
<div id="event-with-method">
<!-- `greet` 是在下面定义的方法名 -->
<button @click="greet("Hello")">Greet</button>
</div>
访问原生dom事件
点击会产生一个原生dom事件
如果我们写@click='greet'
则等价于
greet($event)
这个$event就是原生的dom事件,如果我们传入了参数
则需要greet('Hello',$event)
显示传入$event才可以传入
为什么必须是$event,因为Vue实际在调用的外部包裹了一个函数,其变量名强制设定为了
$event
相当于
function Vue封装函数($event){
greet('Hello',$event)
}
多事件处理
我们可以同时绑定多个事件,使用逗号分割
<!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">
Submit
</button>
事件修饰符
在常见的代码编写之中,我们经常需要调用preventDefault或stopPropagation等函数
preventDeafult阻止了元素的默认行为
如我们点击了a标签链接,通过调用该函数,可以禁止打开链接
stopPropagation阻止了事件的冒泡
如存在
<div><p>click</p></div>
当我们点击click会向上冒泡,事件的上级也会接收到click事件
当我们调用stopPropagation,则会停止冒泡,不会继续向上级传播
我们可以在函数中调用,但是vue提供了一个更好的方式,就是事件修饰符
有
.stop
.prevent
.capture
.self
.once
.passive
我们可以书写如下的代码
<!-- 阻止单击事件继续冒泡 -->
<a @click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form @submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div @click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div @click.self="doThat">...</div>
capture则是在元素自身触发之前
会由上级元素一路捕获到点击元素,而capture相当于在捕获期间触发对应的函数
self则是必须是点击自身元素才可以触发对应函数
修饰符顺序问题
使用修饰符是按顺序进行执行的,如@click.prevent.self会阻止子元素以及自身的默认行为
而@click.self.prevent,只阻止自身,而不阻止子元素的默认行为
举个例子
来源https://www.oschina.net/question/1785591_2273843?sort=default
<div @click="alert(1)">
<a href="/#" @click.prevent.self="alert(2)">
<div @click="alert(3)"></div>
</a>
</div>
这里当我们点击a标签或子元素div标签,都会触发prevent,这时候都会阻止默认行为
如果点击div3
则会触发alert(3)
阻止默认行为,非自身点击,不提示alert(2)
然后提示alert(1)
如果点击div2
阻止默认行为,自身点击,提示alert(2)
然后提示alert(1)
但是如果是.self.prevent
当点击子元素的时候,没有通过.self的运算符,所以不会阻止原生事件触发
只有点击自身元素的时候才会进行事件触发
如果你对两者进行比较,相信发现了区别,修饰符的先后顺序决定了执行结果,vue也是这样处理的
相当于在编译的时候prevent.self变成了
function(){
prevent函数调用
self函数调用
我们的函数调用()
}
我们也有只允许点击一次的语法糖
<a @click.once="doThis"></a>
注意,原生修饰符只能用于dom元素,而once可以应用于组件。相当于它只是一个逻辑上的语法修饰符,而与原生无关
.passive运算符
这里我没有特别理解,大概查了一下资料,可能与事实存在一定的出入
passive用于保证不调用默认阻止事件
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发, -->
<!-- 而不会等待 `onScroll` 完成, -->
<!-- 以防止其中包含 `event.preventDefault()` 的情况 -->
<div @scroll.passive="onScroll">...</div>
通过.passfive保证不调用阻止事件,其默认行为将会立即触发
而不会等待onScroll执行后再触发默认执行事件
该修饰符可以提升移动端的性能。
注意passive不能与prevent一起使用,因为语义冲突
按键修饰符
监听按键修饰符的时候,我们需要检查特定的按键
Vue允许为@或v-on添加按键修饰符
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />
只有按enter的时候才会调用对应函数
可以将键盘事件暴露的任意有限键名转换为横杠写法来作为修饰符
键盘事件可以参考https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
<input @keyup.page-down="onPageDown" />
当事件名为PageDown的时候将会被调用
按键别名
Vue还对常用的键提供了别名
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
系统修饰键
可以用该修饰符来实现按下对应按键才触发监听器
.ctrl
.alt
.shift
.meta
例如
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
tips
修饰符与常规按键不同,在于keyup事件连用
事件触发的时候修饰键必须按下,
只有按下Ctrl的时候触发其他按键
才可以触发keyup.ctrl
单释放ctrl不会触发事件
.exact修饰符
使用exact可以更精准的控制组合事件
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
鼠标按钮修饰符
.left
.right
.middle
会限制函数仅处理特定的鼠标按钮
结语
撒花~