jquery事件
# 事件流
# what is 事件?
鼠标点击click、页面滚动onscroll、鼠标悬停mouseover等对元素的操作称之为事件.
事件绑定: 对HTML元素产生的事件可以绑定具体的操作. eg 在点击某一个元素时触发某个功能的执行.
即之所以绑定事件, 就是因为想要在触发某个操作时去执行一些动作/函数
浏览器中的各种操作不是因为我们绑定事件之后才存在. 即便是我们不对任何元素绑定任何事件,我们仍然可以对元素进行各种如click、mouseover等等操作. 只不过没有为元素绑定事件时, 触发click或mouseover等操作将不会执行任何动作.
# what is 事件流?
事件流描述的是从页面中接收事件的顺序.
html是一个树形嵌套结构
html
|
|___body
|
|___div.box1
|
|____div.box2
<!--
以点击事件为例.
当我们点击div.box2时,由于div.box2在div.box1里,所以我们同时也在点击div.box1;
同理,我们同时也在点击body和html
如果我们为div.box2、div.box1、body、html同时绑定点击事件.
那么在点击div.box2时,该元素的爹、爷爷、祖爷爷...的点击事件都会触发,具体是谁先触发,按照何种顺序触发呢?
这就涉及到下文将阐述的【js事件流】.
-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
js事件流分为三个阶段: 注意: jQuery只有阶段二和阶段三!
1> 事件捕获阶段
2> 处于目标阶段
3> 事件冒泡阶段
打个比方:
以点击事件为例. 整个屏幕相当于一片草地,点击一下屏幕中的某个位置,相当于在屏幕中埋了一颗地雷;
事件捕获 就是扫雷的过程: 从外向里扫雷;
处于目标阶段 就是找到了雷, 然后嘣的一声, 雷爆炸了;
事件冒泡阶段 就是雷爆炸了向外产生的冲击波: 从内向外扩散;
/*
<div class="box1">
<div class="box2"></div>
</div>
*/
// 点击里层的box2盒子,触发box2的点击事件后,外层box1盒子的点击事件也会执行.
$(".box1").click(function () {
console.log("111");
})
$(".box2").click(function () {
console.log("222");
})
/* 浏览器控制台打印执行结果:
"222"
"111"
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
可以通过向文档或者文档中的元素添加“ 事件侦听器 ”addEventListener
来验证上述流程.了解即可!!!
<!--
addEventListener这个方法接收3个参数: 要处理的事件名、事件触发时执行的函数、一个布尔值
布尔值参数如果是true,表示在捕获阶段执行函数;如果是false,表示在冒泡阶段执行函数.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件流</title>
<script>
// window.onload 必须等到页面内包括图片的所有元素加载完毕后才会执行
// 详见0_jquery.md 文档的加载 小节
window.onload = function () {
var oBtn = document.getElementById('btn');
// -- 1> 事件捕获阶段:
// document代表的是整个html页面
document.addEventListener('click', function () {
console.log('document处于事件捕获阶段');
}, true);
// document.documentElement代表的是<html>标签
document.documentElement.addEventListener('click', function () {
console.log('html处于事件捕获阶段');
}, true);
// document.body代表的是<body>标签
document.body.addEventListener('click', function () {
console.log('body处于事件捕获阶段');
}, true);
// 设置了名为'btn'的ID选择器的标签
oBtn.addEventListener('click', function () {
console.log('btn处于事件捕获阶段');
}, true);
// -- 2> 处于目标阶段 略.
// -- 3> 事件冒泡阶段
document.addEventListener('click', function () {
console.log('document处于事件冒泡阶段');
}, false);
document.documentElement.addEventListener('click', function () {
console.log('html处于事件冒泡阶段');
}, false);
document.body.addEventListener('click', function () {
console.log('body处于事件冒泡阶段');
}, false);
oBtn.addEventListener('click', function () {
console.log('btn处于事件冒泡阶段');
}, false);
};
</script>
</head>
<body>
<!--
href="javascript:;" 代表阻止默认事件
eg: a标签的默认事件是跳转; input的submit的默认事件是采集内容提交到后台.
-->
<a href="javascript:;" id="btn">按钮</a>
</body>
</html>
<!-- 浏览器控制台打印结果.
document处于事件捕获阶段
html处于事件捕获阶段
body处于事件捕获阶段
btn处于事件捕获阶段
btn处于事件冒泡阶段
body处于事件冒泡阶段
html处于事件冒泡阶段
document处于事件冒泡阶段
-->
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# 事件委托
事件委托是通过事件冒泡的原理,利用父标签去捕获子标签的事件
效果: 点击按钮新增内容为666的盒子,鼠标悬浮的盒子背景颜色变为橘色,其余盒子背景颜色为白色..
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<style>
ul > li {
list-style: none;
width: 200px;
height: 50px;
border: 1px solid lightcoral;
margin-top: 10px;
text-align: center;
line-height: 50px;
}
</style>
</head>
<body>
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
<li>ddd</li>
<li>eee</li>
</ul>
<!-- 点击一下此按钮,就往ul里新增一个li标签 -->
<button id="btn">点击新增</button>
<script>
/* 发现问题..
// 鼠标在li标签上改变背景颜色的悬浮效果在新增的li标签上不生效!
// 因为代码是从上而下的执行的.它只给body标签里写那几个li标签绑定了鼠标悬浮事件..
// 事件绑定是同步的,绑定事件的触发是异步的 即$('li').mouseover的$('li')只找到了原来的那几个li标签.
$('li').mouseover(function () {
// 链式操作
// 鼠标悬浮在当前元素上时,其背景颜色变为橘色;它的兄弟元素们背景颜色变为白色..
$(this).css('background-color', 'lightsalmon').siblings().css('background-color', 'white')
})
$('#btn').click(function () {
var li = document.createElement('li')
li.innerText = '666'
$(li).appendTo($('ul'))
})
*/
/*
一个愚蠢的解决方案.代码冗余了.(虽然也解决了问题 (´▽`))
总的思想就是给新增的li也绑定鼠标悬浮事件.
// 给原有的li绑定鼠标悬浮事件
$('li').mouseover(function () {
$(this).css('background-color', 'lightsalmon').siblings().css('background-color', 'white')
})
$('#btn').click(function () {
var li = document.createElement('li')
li.innerText = '666'
$(li).appendTo($('ul'))
// 新增后,给全部li标签绑定鼠标悬浮事件 li越来越多,效率会越来越慢
$('li').mouseover(function () {
$(this).css('background-color', 'lightsalmon').siblings().css('background-color', 'white')
})
})
*/
/*
正解:用事件委托! 不给儿子li绑定,给它爹ul绑定
底层就是用的事件冒泡原理,点击li会传递到它父亲ul上..
*/
// on(要绑定的事件,作用到谁身上,触发绑定事件产生的动作)
// 事件是绑定在ul上的,即鼠标悬浮在ul上就会立刻执行function,但此动作是作用在它的儿子li上
$("ul").on("mouseover", "li", function () {
// console.log(this) // this指的是儿子li
$(this).css('background-color', 'lightsalmon').siblings().css('background-color', 'white')
})
$('#btn').click(function () {
var li = document.createElement('li')
li.innerText = '666'
$(li).appendTo($('ul'))
})
</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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# 事件操作
# 鼠标事件
事件 | 说明 |
---|---|
click | 鼠标单击元素 |
dblclick | 鼠标双击元素 |
mousemove | 鼠标移动 |
mousedown | 鼠标左键按下 |
mouseup | 鼠标左键弹起 |
mouseover | 鼠标悬浮在元素上 |
mouseout | 鼠标从元素上移开 |
mouseenter | 效果与mouseover一样, 但 不支持冒泡行为 |
mouseleave | 效果与mouseout一样, 但 不支持冒泡行为 |
focus | 鼠标聚焦, 不支持冒泡 |
blur | 鼠标失去聚焦, 不支持冒泡 |
# 键盘事件
事件 | 说明 |
---|---|
keydown | 键盘按键按下 往输入框内输入内容时, 键盘的任意键按下则触发 应用场景:当用户在最后一个输入框按下回车按键时,表单提交. |
keyup | 键盘按键弹起 往输入框内输入内容时,键盘的任意键抬起则触发 |
# 表单事件
事件 | 说明 |
---|---|
change | 当输入框的内容改变,并且失去焦点时,就会触发 应用场景: 账号密码输错标红后,若未改变就一直标红..改变了再取出来校验一遍. |
select | 选中 输入框的内容时才会被触发 |
submit | 给表单绑定此事件! (给按钮绑定没用) 按下提交按钮时触发. |
<input type="radio" value="男" name="gender">男
<input type="radio" value="女" name="gender">女
<input type="radio" value="未知" name="gender">未知
$(":radio").change(function () {
// 改变选项后获取其value值
console.log($(this).val())
})
/*
//表单事件submit
$('#form').submit(function (event) {
console.log($('input[name=user]').val());
console.log($('input[name=pwd]').val());
event.preventDefault();
});
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 绑定事件和移除事件
/* -- 绑定方式一 */
$('.box1').click(function () {
alert('绑定方式一')
});
/* -- 绑定方式二 */
// 绑定单个事件
$('.box1').bind('click', function () {
alert('绑定方式二')
});
// 绑定多个事件做同一件事
$('.box1').bind('mouseover mouseout', function () {
console.log('绑定多个事件做同一件事')
});
// 绑定多个事件分别做不同的事
$('.box1').bind({
'mouseup': function () {
console.log('mouseover');
},
'mousedown': function () {
console.log('mouseout');
}
});
/* 移除事件 unbind没有参数则代表移除所有事件 */
setTimeout(function () {
alert('3s..mouseover失效');
$('.box1').unbind('mouseover');
}, 3000);
setTimeout(function () {
alert('10s..所有事件移除');
$('.box1').unbind();
}, 10000)
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
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
# 阻止默认事件和冒泡事件
方法一: return false
方法二: event.preventDefault() event.stopPropagation()
方法三: 使用不支持冒泡的事件
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<style>
.father {
width: 300px;
height: 300px;
border: 1px solid gray;
}
.son {
width: 100px;
height: 100px;
background-color: indianred;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
$('.son').mouseout(function () {
console.log("son移出");
/* return false有两个功能
1> 可以取消选中的标签带有的默认事件
2> 阻止冒泡事件
son盒子和father盒子都绑定了mouseout事件
触发son盒子绑定事件的方法时候,会向上冒泡..触发father盒子绑定事件的方法
*/
return false
})
/* 触发事件后,event会收到一个值 -- 当前触发的那个事件
event.type 事件的类型eg:mouseout
event.target 绑定这个事件的元素. 可看作是this
// `return false`的效果等同于下面这两个方法相加
event.preventDefault() 阻止默认事件
event.stopPropagation() 阻止事件冒泡
this和event.target区别:
同 this和event.target都是js dom对象
异 js中事件是会冒泡的,this是会变化的;
event.target不会变化,它永远是直接接受事件的目标js DOM元素
*/
$('.father').mouseout(function (event) {
console.log("father移出");
console.log(event.type); // mouseout
console.log(event.target); // 绑定这个事件的元素
})
</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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
55
56
57