v-on详解
v-on可以监听某个事件,最常用的就是监听onclick事件。还有键盘的事件监听等。我们会一一介绍。
v-on:click监听点击事件
实现一个最简单的计算器功能。
1.v-on:click后面只能跟变量,简单表达式(++,–)或者函数调用。
2.变量不需要mustouch语法,可以直接引用。
<div id="box">
{{counter}}<br>
<button v-on:click="counter++">+</button>
<button v-on:click="counter--">-</button>
</div>
<script type="text/javascript">
var app=new Vue({
el:"#box",
data:{
counter:0
}
})
</script>
运行可以看到简单的计数器效果。
v-on的语法糖
因为onclick事件是非常常用的,我们需要简写的语法糖。可以写成@click。实际上,所有的v-on事件都可以将v-on:xxx写成@xxx的形式,@就表示v-on: 。
<div id="box">
{{counter}}<br>
<button @click="counter++">+</button>
<button @click="counter--">-</button>
</div>
v-on:click 通过函数形式实现
把逻辑直接写在v-on:click后面不太好,代码多了不合适。可以写到单独的函数里面。
<div id="box">
{{counter}}<br>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#box",
data: {
counter: 0
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
})
</script>
v-on参数问题
只是拿click事件举例,参数是v-on所以的事件都有的。
有()和没有()的区别
我们看下面这段代码。我分别点击四个按钮。会出现下面的结果。
非常的好理解,我没有传任何实参,形参当然都是undefined。
<div id="box">
<button @click="btnClick1()">button1</button>
<button @click="btnClick2()">button2</button>
<button @click="btnClick3()">button3</button>
<button @click="btnClick4()">button4</button>
</div>
<script type="text/javascript">
var app=new Vue({
el:"#box",
data:{
},
methods:{
btnClick1(){
console.log("no agrs")
},
btnClick2(name){
console.log(name)
},
//名字是随便取的,但正好传进来的就是event(PointEvent)。
btnClick3(event){
console.log(event)
},
btnClick4(name,event){
console.log(name,event);
}
}
})
现在什么都不变,只是把()去掉,然后分别点击四个按钮。可以看到下面的结果。
可以看到,多出了一个PointerEvent输出。第二行和第三行输出一样,并且第四行最后多输出一个undefine。
直接说为什么,再带入过一遍就明白了。
如果没有(),会默认传一个event参数给第一个形参。
如果没有(),会默认传一个event参数给第一个形参。
如果没有(),会默认传一个event参数给第一个形参。
这就是为什么第二行和第三行会输出PointEvent。第四行的第一个参数也是PointEvent
<button @click="btnClick1">button1</button>
<button @click="btnClick2">button2</button>
<button @click="btnClick3">button3</button>
<button @click="btnClick4">button4</button>
总结: 有()就和正常js一样,该怎么样就怎么样。没有()会默认传一个event参数给第一个形参。 就这么点区别而已。
在v-on中传递手动event参数
在正常js里面的,我们是可以直接传一个event参数的。但在on-v里面不能直接传,也是需要写成 e v e n t 的形式。例如下面的例子。第一个参数 n a m e ,在 d a t a 里面有定义。第二个参数在 d a t a 里面是没有定义的不能直接写。用 event的形式。 例如下面的例子。 第一个参数name,在data里面有定义。第二个参数在data里面是没有定义的不能直接写。用 event的形式。例如下面的例子。第一个参数name,在data里面有定义。第二个参数在data里面是没有定义的不能直接写。用event实际上表示的是这个变量是系统提供的。
<div id="box">
<button @click="btnClick1(name,$event)">button1</button>
</div>
<script type="text/javascript">
var app=new Vue({
el:"#box",
data:{
name:"Tom"
},
methods:{
btnClick1(name,event){
console.log(name,event)
}
}
})
</script>
v-on修饰符
v-on提供了非常多的修饰符,提供修饰符可以解决一些常见的问题,完成的分别。下面举几个常用的修饰符。
.stop修饰符
.stop
是 event.stopPropagation()
的别名。在触发 DOM 事件时,会阻止事件继续传播到父元素。(浏览器默认使用的冒泡)
这两个修饰符的主要区别在于它们处理事件的方式:
.stop
是阻止事件冒泡,也就是阻止事件在 DOM 树中向上传播。例如,如果你在一个按钮的点击事件处理函数中使用了.stop
,那么这个点击事件不会触发该按钮的父元素的点击事件处理函数。
下面的代码实现div包裹一个button,同时给div和button设置onclick。点击按钮的时候,会输出下面两个代码,可以看到,是button先输出,div后输出,这表明onclick的触发顺序是从里到外的。
<div id="box" @click="divClick">
<button class="innerBtn" @click.stop="btnClick">button</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#box",
data: {},
methods: {
btnClick(){
console.log("btnClick")
},
divClick(){
console.log("divClick")
}
}
})
</script>
#box {
width: 200px;
height: 200px;
background-color: lightgreen;
}
这样不太好,我只希望点button的时候,只有button的点击事件触发。这时候就可以提供.stop修饰符来实现,只需要给button的@click修改为@click.stop就可以实现这样的功能。
<div id="box" @click="divClick">
<button class="innerBtn" @click="btnClick.stop">button</button>
</div>
.prevent修饰符
.prevent修饰符可以阻止默认的点击事件。例如下面的代码,点击submit,默认是会提交表单,但我想在自己定义的gotoWeb里面来执行,我手动调用跳转方法,而不是用你默认的,这样我可以做一些额外的处理。光写gotoweb这个方法是不够的,这样还是会执行表达的提交事件,给@click添加.prevent,就可以阻止表单提交,这样就只有gotoweb方法会被执行。
.prevent修饰符可以用于任何有默认事件的控件。用来阻止默认事件。
<!--2.prevent-->
<div id="box" >
<form action="http://wwww.baidu.com" method="get">
<input type="submit" value="submit" @click.prevent="gotoWeb()">
</form>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#box",
data: {},
methods: {
gotoWeb(){
console.log("goto web")
}
}
})
</script>
capcure修饰符
添加之后就是把默认的冒泡模式改为捕获模式。
分别点击1 2 3 事件输出如下。第一行div1Click输出两次。好好试一下,这个demo,对面试非常有帮助。
把.capture全部去除,默认的冒泡事件如下。
键位修饰符
用@keydown监听键盘按下,所以的键都会触发keydown函数,但我们只想按回车的时候才触发keydown函数,这时候就可以用.enter修饰@keydown,表示只监听回车键。
<!--2.key-->
<div id="box" >
<input type="text" @keydown.enter="keydown">
</div>
<script type="text/javascript">
var app = new Vue({
el: "#box",
data: {},
methods: {
keydown(){
console.log("keydown")
}
}
})
</script>
.once修饰符
事件只会执行一次,比如用.once修饰后,点击事件只会执行一次,有时候有用。
.self修饰符
事件只在点击的事件上发生,不进行事件传递。我觉得这个修饰符比stop和capture更简单好用,因为不需要关心是冒泡还是捕获,在只想处理具体按钮事件的时候简单好用。
分别点击div1 2 3。事件如下,只会触发各自的点击事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<style rel="stylesheet">
#box1 {
width: 200px;
height: 200px;
background-color: lightgreen;
}
#box2 {
width: 180px;
height: 180px;
background-color: lightskyblue;
}
#box3 {
width: 160px;
height: 160px;
background-color: lightsalmon;
}
</style>
</head>
<body>
<!--1.stop-->
<div id="box1" @click.self="div1Click">
div1
<div id="box2" @click.self="div2Click">
div2
<div id="box3" @click.self="div3Click">div3</div>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#box1",
data: {},
methods: {
div1Click() {
console.log("div1Click")
},
div2Click() {
console.log("div2Click")
},
div3Click() {
console.log("div3Click")
},
}
})
</script>
</body>
</html>
.passive修饰符
这个修饰符就是用来提高触碰事件的性能的。
规范的默认值是false,但浏览器为了提高性能,已经在一些顶层事件中设置为true。所以你几乎不需要修改这个值。
<div @scroll.passive="onScroll">...</div>