目录
@click.prevent.self和@click.self.prevent区别
@click的方法只写了方法名没括号?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue中的事件处理</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<button @click="handleClick">Button</button>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleClick(e) {
console.log(e);
}
}
})
</script>
</body>
</html>
点击按钮之后控制台打印如下:
调用方法只写了方法名没写括号,怎么看起来不像是调用方法。但是就是这样调用的,如果我们加上了括号会怎么样呢?
<button @click="handleClick()">Button</button>
点击按钮之后如下:
这样就获取不到事件event对象了,点击直接当成普通函数,传参数为undefined
真的只能放方法名吗?但是我想手动传参数怎么办?
@click方法写上参数
<button @click="handleClick">Button</button>
等同于
<button @click="handleClick($event)">Button</button>
带上$event参数是vue内置的事件对象的写法,这和上面只写方法名效果一样。
第二种写法有什么好处呢?这样不但可以传事件对象,还可以传其他参数,来看看
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue中的事件处理</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<button @click="handleClick($event, 1, 2, 3)">Button</button>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleClick(e, one, two, three) {
console.log(e, one, two, three);
console.log(arguments);
}
}
})
</script>
</body>
</html>
点击按钮之后的运行结果:
事件的修饰符
@click.prevent
这个例子并不会跳转到/abc,因为加了事件修饰符prevent,能够阻止事件的默认行为
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue中的事件处理</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<form action="/abc">
<input type="submit" @click.prevent/>
</form>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
}
})
</script>
</body>
</html>
vue提供了事件修饰的语法,prevent就是一个事件修饰符,如果还有其他方法,就是@click.prevent="你的方法名",点击后执行方法,但是阻止你的提交行为。
如果不写prevent,那么应该这样实现同样的功能
<div id="app">
<form action="/abc">
<input type="submit" @click="handleClick"/>
</form>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleClick(e) {
e.preventDefault();
}
}
})
</script>
但是这样写就没有好好利用vue的特性了,有修饰符不是更方便嘛
@click.stop与@click.prevent
@click.stop 阻止事件冒泡
@click.prevent 阻止事件的默认行为
<a href="http://www.baidu.com" @click.prevent="test4">百度一下</a> //阻止a标签跳转,仅执行函数test4
<a href="tel:10086" @click.prevent>10086</a> // 阻止拨打电话,这是个坑,在移动端需要注意
另外,href="tel:10086"在ios端点击一次是无法拨打的,很容易被忽略,ios必须长按这里这个链接才会提示是否拨打电话,而在android点一下就可以跳转到拨号页面,ios想和android点一下就拨打需要进一步的处理
<form action="/xxx" @submit.prevent="test5"> //阻止表单提交,仅执行函数test5
<input type="submit" value="注册">
</form>
@click.capture(捕获)
<div v-on:click.capture="doThis">...</div>
意思就是不加.capture是事件冒泡(默认就是冒泡),加上.capture就是事件捕获,若有多个该修饰符,则由外而内触发。
就是谁有该事件修饰符,就先触发谁。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>事件捕获与冒泡</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<div @click="f1"
style="width:500px;height:500px;background-color:red">
<div @click.capture="f2"
style="width:300px;height:300px;background-color:green">
<div @click.capture="f3"
style="width:100px;height:100px;background-color:blue">
<div @click="f4"
style="width:50px;height:50px;background-color:pink"></div>
</div>
</div>
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
f1() {
console.log('==1')
},
f2() {
console.log('-----2')
},
f3() {
console.log('===3')
},
f4() {
console.log('===4')
}
}
})
</script>
</body>
</html>
最外层的div:500*500px->red
次外层的div:300*300px->green
中层的div:100*100px->blue
最内层的div:50*50px->pink
这里capture次外层,最内层,所以点击内层触发依次为
-----2
===3
===4
==1
说明:
点击事件先看事件捕获,然后再看事件冒泡
先触发的都是capture(都有capture的情况下从外到内依次触发),其次再是默认冒泡的(由内而外依次触发)
这里优先capture由外到内触发2、3,接着由内到外冒泡 4、1
来一张图
@click.self
使用.self实现只有点击当前元素的时候,才会触发事件处理函数。即加了.self的元素上e.target === e.currentTarget为true的时候才执行
e.target表示的是点击的元素,而e.currentTarget在事件冒泡或者捕获阶段会变化,比如冒泡时e.currentTarget会不断指向往上冒的对象,而e.target还是最初点击的对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>.self</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<div @click.self="handleClick">
这行内在.self的直接管辖内
<div @click="hello2">
<div @click="hello">hello world</div>
</div>
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleClick(e) {
alert("点击了我.self的直接管辖范围");
console.log(".self直接管辖范围内的e.target == e.currentTarget:" + (e.target === e.currentTarget));
},
hello(e) {
console.log("hello world");
console.log("hello的div的e.target === e.currentTarget: " + (e.target === e.currentTarget));
},
hello2(e) {
console.log("hello2中间层div的e.target === e.currentTarget: " + (e.target === e.currentTarget));
},
}
})
</script>
</body>
</html>
运行结果如下:
这段代码看到@click.self,这怎么看起来是阻止了冒泡,确实从现象上来看是这样,但是这个应该解释为,点击子元素仍然会冒泡,但是我不接,你只有点击.self直接管辖范围内时候我才执行handleClick(你必须要点我才行,点我的子元素就不行,就算冒泡上来、捕获下去我也都会忽略)
看一下下面代码:
<div id="app" v-on:click.self="close">
<button>点击</button>
</div>
不管你怎么点击按钮,都不会去执行close方法,因为你的self会忽略冒泡,除非这里的div是@click="close"才会收到子元素的冒泡去执行close方法。
@click.prevent.self和@click.self.prevent区别
<div @click="alert(1)">
<a href="/#" @click.prevent.self="alert(2)">
.self直接范围
<div @click="alert(3)">123123</div>
</a>
</div>
// 点击最内层div,会alert3,alert1。不但忽略了alert(2),还阻止了a的默认跳转。
// 因为点击的时候会先prevent,阻止默认事件跳转;然后判断是否是.self直接管辖范围的e.target===e.currentTarget是否为true
// 因为点击的最内层的div,所以.self直接管辖范围的e.target===e.currentTarget是false,忽略了alert(2)。
<div @click="alert(1)">
<a href="/#" @click.self.prevent="alert(2)">
.self直接范围
<div @click="alert(3)">123123</div>
</a>
</div>
// 点击最内层div,会alert3,alert1,跳转到/#。只忽略了alert(2)。
// 这里不会执行alert(2),理由同上,但是可以跳转。
prevent在self前,阻止默认跳转,prevent在self后,那跳转就阻止不了
@click.once
once:绑定的事件仅生效一次,然后就解绑。一般与点击事件配合使用,比如@click.once。使得只可以点击一次。
比如:
<button @click.once='alert("我就第一次出现")'>点击</button>
又比如
<a href="https://www.baidu.com" @click.prevent.once> 第一次点击被阻止</a>
这个链接点击第二次及以后都可以跳转,第一次被阻止
更多事件修饰符可以见官网:事件修饰符
按键修饰符keydown
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue中的事件处理</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<input @keydown="handleKeyDown">
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleKeyDown() {
console.log(e.target.value);
}
}
})
</script>
</body>
</html>
这里是当按下鼠标的时候就触发handleKeyDown方法,所以按下任意一个键,比如数字1,控制台打印""空串,因为按下的瞬间input框还没有东西。
如果是@keyup则就是松开键盘的一瞬间打印input框里面的值,如果长按“2”,在input不断输入2,放开手,控制台只会打印一次一长串的2。
要注意的是,可能你输入的过快,比如快速分别按下123,则控制台可能会显示3个123,或者一个1,两个123等等情形(在mac都可以复现,在window不会复现)
@keyup.enter松开按键并不会触发,之后按下回车enter的时候才会触发
按键修饰符有
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
更多按键修饰符见官网:按键修饰符
系统修饰键
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue中的事件处理</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<input @keyup.ctrl="handleKeyUp" />
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleKeyUp(e) {
console.log(e.target.value);
}
},
})
</script>
</body>
</html>
在input框输入之后,并不会在控制台显示,比如按住ctrl后再输入才会同步到控制台
系统修饰符有
.ctrl
.alt
.shift
.meta
更多系统修饰符见官网:系统修饰键
鼠标按钮按钮修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>mouse click</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<div @click.left="handleLeft" @click.right="handleRight">mouse click</div>
</div>
<script>
var vm = new Vue({
el: "#app",
methods: {
handleLeft(e) {
console.log("mouse left");
},
handleRight(e) {
console.log("mouse right");
}
},
})
</script>
</body>
</html>
运行结果:
关注、留言,我们一起学习。
===============Talk is cheap, show me the code================