Vue基础知识-(三)事件

本文最后更新于:January 3, 2022 pm

Vue(读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,方便与第三方库或既有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

目录

1.事件处理

使用指令:v-on:,可以简写为@

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<button type="button" v-on:click="showInfo()">点击触发</button>
//简写
<button type="button" @click="showInfo()">点击触发</button>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(){
alert('奥利给!')
}
}
})

</script>
</body>
</html>

也可以在showInfo()方法中,获取发送事件的目标。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<button type="button" v-on:click="showInfo">点击触发</button> <br>
<button type="button" @click="showInfo">点击触发</button>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(event){
console.log(event.target)
alert('奥利给!')
}
}
})

</script>
</body>
</html>

📢注意:方法调用处和方法处是有区别的!

也可以进而获取元素内容。

带参方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<button type="button" v-on:click="showInfo1">点击触发1111</button> <br>
<button type="button" @click="showInfo2($event,66)">点击触发22222</button>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo1(event){
console.log(event.target)
alert('奥利给!')
},
showInfo2(a,num){
console.log(a.target)
console.log(a,num)
alert('奥利给!')
}
}
})

</script>
</body>
</html>

$event是占用符,用来接收event

2.事件修饰符

2.1 默认行为(prevent)

阻止默认行为。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<a href="https://www.baidu.com" @click="showInfo">点击跳转</a>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(){
alert('奥利给!')
}
}
})

</script>
</body>
</html>

这样在点击后,会先弹窗,再跳转。因为跳转是a标签的默认行为。阻止默认行为有两种方式:

其他相同部分就不再写,只写有变化的部分。

方式一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(e){
e.preventDefault() //阻止默认行为
alert('奥利给!')
}
}
})

</script>

方式二:

1
<a href="https://www.baidu.com" @click.prevent="showInfo">点击跳转</a>

两种实现效果一样。

2.2 事件冒泡(stop)

阻止事件冒泡。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<div class="demo2" @click="showInfo">
<button type="button" @click="showInfo">点击跳转</button>
</div>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(e){
// e.preventDefault()
alert('奥利给!')
}
}
})

</script>
</body>
</html>

在点击按钮后,会出现两次弹窗。这就是事件冒泡。点的是按钮,但最后冒到了外面一层。解决办法也是有两种:

其他相同部分就不再写,只写有变化的部分。

方式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(e){
e.stopPropagation() //阻止事件冒泡
alert('奥利给!')
}
}
})

</script>

方式二

1
2
3
<div class="demo2" @click="showInfo">
<button type="button" @click.stop="showInfo">点击跳转</button>
</div>

📢注意:stop是加在了里面的按钮上,而不是外面的div。如果div外还有一层,则在div上还要再加!

2.3 只触发一次(once)

默认情况下一个按钮弹窗,点一次会弹一次。如果只希望在第一次点了之后就不能再点了,就可以使用once实现。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<button type="button" @click.once="showInfo">点击跳转</button>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showInfo(e){
// e.stopPropagation()
alert('奥利给!')
}
}
})

</script>
</body>
</html>

2.4 捕获模式(capture)

默认情况下是先捕获,后冒泡执行。现在就是让Vue在捕获阶段就执行。(捕获是从外到内,冒泡是从内到外 。即从点的(触发点)的地方开始向外执行,而此模式就是在捕获阶段就执行。因为捕获是先从外到内进行捕获,执行的时候再从内到外执行。)

默认情况下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: #87CEEB;
}
.box2{
padding: 5px;
background-color: orange;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<div class="box1" @click="showM(1)">box1
<div class="box2" @click="showM(2)">box2</div>
</div>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
alert(m)
}
}
})

</script>
</body>
</html>

使用capture

将capture放在外面层的div上,表示从外层开始在捕获阶段就执行,不用等到冒泡时才执行。

1
2
3
4
5
6
7
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<div class="box1" @click.capture="showM(1)">box1
<div class="box2" @click="showM(2)">box2</div>
</div>
</div>

2.5 目标为当前操作元素才触发(self)

只有event.target是当前操作的元素时才触发时间。白话就是:如果一个div中套了一个button,并且两个都有触发时间,当你点了button时,只有button才会执行,div不会执行。类似于阻止冒泡的。

未使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: #87CEEB;
}
.box2{
padding: 5px;
background-color: orange;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<div class="demo2" @click="showM">box1
<button type="button" @click="showM">点击</button>
</div>
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
console.log(m.target)
}
}
})

</script>
</body>
</html>

使用修饰符:

1
2
3
4
5
6
7
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<div class="demo2" @click.self="showM">box1
<button type="button" @click="showM">点击</button>
</div>
</div>

用在需要判定当前的被修饰的元素是否是触发源。在上面例子中,button是触发源。

3.键盘事件

常用的两个:一个是@keyup(按下抬起触发),一个是@keydown(按下触发)。

3.1 字符编码

查看一些键的编码为多少。在输入框中输入,控制台上可以看见此字符的编码为多少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: #87CEEB;
}
.box2{
padding: 5px;
background-color: orange;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<input type="text" @keyup="showM" />
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
console.log(m.keyCode)
}
}
})

</script>
</body>
</html>

但是,通过此用例也可以看见,我们并没有按回车就输出了。一般来说加一个判断即可。如:

1
2
3
4
5
showM(m){
if(m.keyCode !== 13) return
console.log(m.keyCode)
console.log(m.target.value)
}

但是,用vue比较方便,即:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: #87CEEB;
}
.box2{
padding: 5px;
background-color: orange;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<input type="text" @keyup.enter="showM" /> //区别
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
console.log(m.keyCode)
console.log(m.target.value)
}
}
})

</script>
</body>
</html>

3.2 字符别名

其中,使用的enter是其对应编码的别名,还有一些其他的别名,如下:

  1. 回车 => enter,回车真正的名字:Enter,用此名字也可以。
  2. 删除 => delete(删除、退格键)
  3. 退出 => esc
  4. 空格 => space
  5. 换行 => tab(特殊,使用keydown检验)
  6. 上 => up
  7. 下 => down
  8. 左 => left
  9. 右 => right

可自行尝试。

Vue未提供别名的按键,可以使用按键原始的key值去绑定,但需要注意的是要转为kebab-case(短横线命名),如CapsLock => caps-lock

获取按键的名字和keyCode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="./js/vue.js"></script>
<style type="text/css">
*{
margin-top:20px;
}
.demo2{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: #87CEEB;
}
.box2{
padding: 5px;
background-color: orange;
}
</style>
</head>
<body>
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<input type="text" @keyup="showM" />
</div>

<script type="text/javascript">
Vue.config.productionTip = false

//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
console.log(m.key,m.keyCode)
}
}
})

</script>
</body>
</html>

注意:有一些按键是不能绑定的。

3.3 特殊按键

系统修饰键:ctrl、alt、shift、meta。

  1. 配合keyup使用:按下修饰键的同时,再按其他键(任意),在释放其他键后事件才被触发。
  2. 配合keydown使用:正常触发。

3.4 自定义别名

Vue.config.keyCodes.别名 = 简码

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="root">
<h1>hello,{{name}}</h1>
<h2>年龄:{{age}}</h2>
<input type="text" @keyup.huiche="showM" />
</div>
<script type="text/javascript">
Vue.config.productionTip = false
Vue.config.keyCodes.huiche = 13 //为回车键定义别名
//创建vue示例
const x = new Vue({
el:'#root',
data:{
name:'loong',
age:23
},
methods:{
showM(m){
console.log(m.key,m.keyCode)
}
}
})

</script>

4.总结

  1. 修饰符可以连着写(谁先写谁先执行)。如

    1
    2
    3
    <div class="demo1" @click="showM">
    <a href="http://www.baidu.com" @lick.stop.prevent="showM"></a>
    </div>
  2. 指定按键触发。如:按键ctrl+y触发 :

    1
    <input type="text" @keyup.ctrl.y="showM" />