DOM 的概念
• 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和 www 文档的风格(目前,HTML 和 XML 文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM 是一种基于树的 API 文档,它要求在处理过程中整个文档都表示在存储器中。
DOM 树
• DOM 又称为文档树模型
• - 文档:一个网页可以称为文档
• - 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
• - 元素:网页中的标签
• - 属性:标签的属性
DOM 经常进行的操作
• 获取元素
• 对元素进行操作(设置其属性或调用其方法)
• 动态创建元素
• 事件(什么时机做相应的操作)
DOM 获取页面元素
获取页面元素
• 为什么要获取页面元素?
• 例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,才进行后续操作。
根据 id 获取元素
• 方法:调用 document 对象的 getElementById 方法。
• 参数:字符串类型的 id 的属性值。
• 返回值:对应 id 名的元素对象。
• 注意1:由于 id 名具有唯一性,部分浏览器支持直接使用 id 名访问元素,但不是标准方式,不推荐使用。
• 注意2:代码执行顺序,如果 js 在 html 结构之前,会导致结构未加载,不能获取对应id的元素。
• 注意3:id名具有唯一性,同时书写两个相同的id名,只会执行第一个。
根据标签名获取元素
• 方法:调用 document 对象的 getElementsByTagName 方法。
• 参数:字符串类型的标签名。
• 返回值:同名的元素对象组成的数组。
• 注意1:操作数据时需要按照操作数组的方法进行。
• 注意2:getElementsByTagName 方法内部获取的元素是动态增加的。
元素对象内部获取标签元素
• 获取的元素对象内部,本身也可以调用根据标签获取元素方法,例如 div 元素对象也可以调用 getElementsByTagName 方法。
• 目的:缩小选择元素的范围,类似 css 中的后代选择器
根据 name 获取元素
• 方法:调用 document 对象的 getElementsByName 方法。
• 参数:字符串类型的 name 属性值。
• 返回值:name 属性值相同的元素对象组成的数组。
• 不建议使用:在 IE 和 Opera 中有兼容问题,会多选中 id 属性值相同的元素。
Nodelist :节点(标签、属性、文本、注释等) 列表集合,类数组
方法选中的元素也是动态变化的
根据类名获取元素
• 方法:调用 document 对象的 getElementsByClassName 方法。
• 参数:字符串类型的 class 属性值。
• 返回值:class 属性值相同的元素对象组成的数组。
• 浏览器兼容问题:不支持 IE8 及以下的浏览器
方法选中的元素也是动态变化的
根据选择器获取元素
• 方法1:调用 document 对象的 querySelector 方法,通过 css 中的选择器去选取第一个符合条件的标签元素。
• 方法2:调用 document 对象的 querySelectorAll 方法,通过 css 中的选择器去选取所有符合条件的标签元素。
• 参数:字符串类型的 css 中的选择器。
• 浏览器兼容问题:不支持 IE8 以下的浏览
必须在结构加载完成后书写,不能写在前面。
总结
掌握,没有兼容问题
• getElementById()
• getElementsByTagName()
了解
• getElementsByName()
• getElementsByClassName()
• querySelector()
• querySelectorAll()
DOM 事件基本应用
事件
• 事件:在什么时候做什么事
• 执行机制:触发–响应机制
• 绑定事件(注册事件)三要素:
1、事件源:给谁绑定事件
2、事件类型:绑定什么类型的事件 click 单击
3、事件函数:事件发生后执行什么内容,写在函数内部
事件监听
• JavaScript 解析器会给有绑定事件的元素添加一个监听,解析器会一直监测这个元素,只要触发对应的绑定事件,会立刻执行事件函数。
常用事件监听方法
• 方法1:绑定 HTML 元素属性。
• 方法2:绑定 DOM 对象属性
常用的鼠标事件类型
• onclick 鼠标左键单击触发
• ondbclick 鼠标左键双击触发
• onmousedown 鼠标按键按下触发
• onmouseup 鼠标按键放开时触发
• onmousemove 鼠标在元素上移动触发
• onmouseover 鼠标移动到元素上触发
• onmouseout 鼠标移出元素边界触发
案例:
• 点击按钮弹出提示框
DOM 元素属性操作
非表单元素的属性
• 例如:href、title、id、src 等。
• 调用方式:元素对象打点调用属性名,例如 obj.href。
• 注意:部分的属性名跟关键字和保留字冲突,会更换写法。
- class → className
- for → htmlFor
- rowspan → rowSpan
• 属性赋值:给元素属性赋值,等号右侧的赋值都是字符串格式。
案例
•点击按钮切换图片
• 点击按钮显示隐藏 div
• 美女相册
获取标签内部内容的属性
• 获取标签内部内容的属性有两个:innerHTML 和 innerText
• innerHTML属性,在获取标签内部内容时,如果包含标签,获取的内容会包含标签,获取的
内容包括空白换行等。
• innerText属性,在获取标签内部内容时,如果包含标签,获取的内容会过滤标签,获取的
内容会去掉换行和缩进等空白。
更改标签内容
还可以通过两个属性给双标签内部去更改内容:
• innerHTML 设置属性值,有标签的字符串,会按照 HTML 语法中的标签加载。
• innerText 设置属性值,有标签的字符串,会按照普通的字符加载。
对比使用场景
• innerText:在设置纯字符串时使用。
• innerHTML:在设置有内部子标签结构时使用。
表单元素属性
• value 用于大部分表单元素的内容获取(option除外)
• type 可以获取input标签的类型(输入框或复选框等)
• disabled 禁用属性
• checked 复选框选中属性
• selected 下拉菜单选中属性
• 注意:在 DOM 中元素对象的属性值只有一个时,会被转成布尔值显示。
例如:txt.disabled = true;
案例
• 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框
• 设置下拉框中的选中项
• 搜索文本框
• 全选反选
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { padding: 0; margin: 0; } .wrap { width: 300px; margin: 100px auto 0; } table { border-collapse: collapse; border-spacing: 0; border: 1px solid #c0c0c0; width: 300px; } th, td { border: 1px solid #d0d0d0; color: #404060; padding: 10px; } th { background-color: #09c; font: bold 16px "微软雅黑"; color: #fff; } td { font: 14px "微软雅黑"; } tbody tr { background-color: #f0f0f0; } tbody tr:hover { cursor: pointer; background-color: #fafafa; } </style> </head> <body> <div class="wrap"> <table> <thead> <tr> <th> <input type="checkbox" id="all" /> </th> <th>商品</th> <th>价钱</th> </tr> </thead> <tbody id="tb"> <tr> <td> <input type="checkbox" /> </td> <td>iPhone8</td> <td>8000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Pro</td> <td>5000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>iPad Air</td> <td>2000</td> </tr> <tr> <td> <input type="checkbox" /> </td> <td>Apple Watch</td> <td>2000</td> </tr> </tbody> </table> <input type="button" value=" 反 选 " id="btn"> </div> <script> // 获取元素 var all = document.getElementById("all"); var tb = document.getElementById("tb"); var btn = document.getElementById("btn"); var tb_inputs = tb.getElementsByTagName("input"); // 1.全选:让子选项的选择效果始终与全选保持一致 all.onclick = function() { // 遍历所有的子选项 for (var i = 0; i < tb_inputs.length; i++) { // 让每一个子选项的 checked 属性值与全选保持一致 tb_inputs[i].checked = all.checked; } }; // 2.单独选择子选项过程 // 给每一次点击任何一个子选项进行判断 for (var i = 0; i < tb_inputs.length; i++) { tb_inputs[i].onclick = function() { // 需要判断所有的子选项是否都是选中的状态,如果都选中,让全选被选中,如果有的没有被选中,让全选取消选择 allChecked(); } } // 3.反选 btn.onclick = function() { // 让所有子选项与之前的状态相反 for (var i = 0; i < tb_inputs.length; i++) { // 让属性值取原来相反的值 tb_inputs[i].checked = !tb_inputs[i].checked; } // 控制全选效果,也需要进行取反 allChecked(); }; // 定义一个 all 是否被选中的函数 function allChecked() { // 使用一个中间过渡变量,初始认为所有的子选项都是被选中的 var isAllChecked = true; // 遍历所有子选项,进行判断 for (var j = 0; j < tb_inputs.length; j++) { // 一旦有一个是没有被选择的,让变量变为 false if (tb_inputs[j].checked === false) { isAllChecked = false; // 只要走到这里,说明肯定不是全选,不需要往下执行循环 break; } } // 如果循环内部条件永远不成立,说明所有子选项都是被选中,isAllChecked 的值没有发生变化,还是 true // 给 all 元素设置 checked 属性 all.checked = isAllChecked; } </script> </body> </html>
自定义属性操作
• getAttribute(name) 获取标签行内属性
• setAttribute(name,value) 设置标签行内属性
• removeAttribute(name) 移除标签行内属性
• 与element.属性的区别: 上述三个方法用于获取任意的行内属性,包括自定义的属性。
style 样式属性操作
• 使用 style 属性方式设置的样式显示在标签行内。
• element.style 属性的值,是所有行内样式组成的一个样式对象。
• 样式对象可以继续点语法调用或更改 css 的行内样式属性,例如 width、height 等属性。
• 注意1:类似 background-color 这种复合属性的单一属性写法,是由多个单词组成的,要
修改为驼峰命名方式书写 backgroundColor。
• 注意2:通过样式属性设置宽高、位置的属性类型是字符串,需要加上 px 等单位。
className 类名属性操作
• 修改元素的 className 属性相当于直接修改标签的类名。
• 如果需要修改多条 css 样式,可以提前将修改后的样式设置到一个类选择器中,后续通过
修改类名的方式,批量修改 css 样式。
案例
• 开关灯
1
2
3
4function my$(id) { return document.getElementById(id); }
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<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <input type="button" value="关灯" id="btn"> <script src="common.js"></script> <script> // 获取元素 var btn = my$("btn"); // console.log(btn); // 定义一个判断变量,true 表示开灯状态,false 表示关灯状态 // var isOpen = true; // 点击事件,控制 body 的背景 btn.onclick = function () { // 开灯时,需要点击后让它关灯并切换文字为 开灯 // if (isOpen) { // document.body.style.backgroundColor = "black"; // this.value = "开灯"; // isOpen = false; // } else { // document.body.style.backgroundColor = "white"; // this.value = "关灯"; // isOpen = true; // } // 直接使用 btn 的 value 值进行判断 if (this.value === "关灯") { document.body.style.backgroundColor = "black"; this.value = "开灯"; } else { document.body.style.backgroundColor = "white"; this.value = "关灯"; } }; </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<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> .box { width: 50px; height: 50px; background: url(images/bgs.png) no-repeat -159px -51px; position: fixed; right: 10px; top: 40%; } .erweima { position: absolute; top: 0; left: -150px; } .box a { display: block; width: 50px; height: 50px; } .hide { display: none; } .show { display: block; } </style> </head> <body> <div class="box" id="box"> <div class="erweima hide" id="er"> <img src="images/456.png" alt=""/> </div> </div> <script src="common.js"></script> <script> // 获取元素 var box = my$("box"); var er = my$("er"); // 给 box 添加鼠标移上事件 onmouseover ,添加鼠标离开事件 onmouseout box.onmouseover = function () { // 让子级元素进行显示,就是将 hide 改为 show // er.className = "erweima show"; er.className = er.className.replace("hide","show"); }; box.onmouseout = function () { // 让子级元素进行隐藏,就是将 show 改为 hide // er.className = "erweima hide"; er.className = er.className.replace("show","hide"); }; </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<!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>Document</title> </head> <body> <input type="text"><br> <input type="text"><br> <input type="text"><br> <input type="text"><br> <input type="text"><br> <input type="text"><br> <input type="text"><br> <button id="btn">按钮</button> <script> // 获取元素 var txts = document.getElementsByTagName("input"); // 添加批量的获取焦点事件 for (var i = 0; i < txts.length; i++) { // 排他思想:1.排除其他 2.保留自己 // 给每一个input标签添加获取焦点事件 txts[i].onfocus = function() { // 排除其他的方法:将所有的项包含自己都设置为默认样式 // 遍历数组,让所有的样式恢复默认 for (var j = 0; j < txts.length; j++) { txts[j].style.backgroundColor = ""; } // 设置元素自己高亮显示 // 保留自己的特殊样式 // this 指代事件源自己 this.style.backgroundColor = "yellow"; }; } </script> </body> </html>
• 点击按钮改变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<!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>Document</title> <style> div { width: 100px; height: 100px; background-color: pink; } .new { position: absolute; width: 200px; height: 200px; left: 200px; top: 200px; } </style> </head> <body> <input type="button" value="按钮" id="btn"> <div id="box"></div> <script src="common.js"></script> <script> //获取元素 var btn = my$("btn"); var box = my$("box"); // 添加事件 btn.onclick = function() { // 修改类名 // box.className = "new"; // 修改 style 样式对象中的属性 box.style.width = "200px"; box.style.height = "200px"; box.style.left = "200px"; box.style.top = "200px"; box.style.position = "absolute"; }; </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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106<!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>Document</title> <style> td { width: 100px; height: 40px; } </style> </head> <body> <table border="1" style="border-collapse: collapse;"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </table> <script> // 获取所有的行 var trs = document.getElementsByTagName("tr"); // 1.隔行变色 for (var i = 0; i < trs.length; i++) { // 下标为偶数的行显示粉色 // 下标为奇数的行显示灰色 if (i % 2 == 0) { trs[i].style.backgroundColor = "pink"; } else { trs[i].style.backgroundColor = "lightgray"; } // 2.鼠标移上高亮显示,鼠标离开恢复默认 // 全局变量 var bgc; // 鼠标移上高亮显示 trs[i].onmouseover = function() { // 定义变量记录 tr 原来的颜色 bgc = this.style.backgroundColor; this.style.backgroundColor = "skyblue"; }; // 鼠标离开恢复默认 trs[i].onmouseout = function() { this.style.backgroundColor = bgc; }; } </script> </body> </html>
• tab选项卡切换
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
90
91
92
93
94
95
96<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * {margin:0; padding: 0;} ul { list-style-type: none; } .box { width: 400px; height: 300px; border: 1px solid #ccc; margin: 100px auto; overflow: hidden; } .hd { height: 45px; } .hd span { display:inline-block; width: 90px; background-color: pink; line-height: 45px; text-align: center; cursor: pointer; } .hd span.current { background-color: skyblue; } .bd div { height: 255px; background-color: skyblue; display: none; } .bd div.current { display: block; } </style> </head> <body> <div class="box"> <div class="hd" id="hd"> <span class="current">体育</span> <span>娱乐</span> <span>新闻</span> <span>综合</span> </div> <div class="bd" id="bd"> <div class="current">我是体育模块</div> <div>我是娱乐模块</div> <div>我是新闻模块</div> <div>我是综合模块</div> </div> </div> <script src="common.js"></script> <script> // 获取元素 var hd = my$("hd"); var spans = hd.getElementsByTagName("span"); var bd = my$("bd"); var divs = bd.getElementsByTagName("div"); // 鼠标移上某个 span 让它添加一个类名,其他的失去类名 for (var i = 0 ; i < spans.length ; i++) { // 给每一个 span 元素添加一个新的属性,记录自己在数组中的下标 spans[i].index = i; spans[i].onmouseover = function () { // console.dir(this); // 1.让 span 自己进行切换 // 排他思想: // 排除其他 for (var j = 0; j < spans.length ; j++) { spans[j].className = ""; // 由于 divs 中数据个数与 spans 一样,所以可以再同一个遍历循环中,进行排他操作 divs[j].className = ""; } // 保留自己 this.className = "current"; // console.log(this.index); // 2.让 bd 中的 div 也对应进行切换 // 对应控制思想:有两组数据中存储了相同个数的元素对象,一组对象的变化,会引起另外一组的变化 // 实现方法:找两个数据中的共同点,两个数组中元素对象的下标是一样的 // 对应控制中也会涉及到排他的操作 // 保留 div 自己的类名 divs[this.index].className = "current"; }; } </script> </body> </html>
DOM 节点操作
节点属性
• nodeType 节点的类型,属性值为数字,表示不同的节点类型,共 12 种,只读
1 元素节点
2 属性节点
3 文本节点
• nodeName 节点的名称(标签名称),只读
• nodeValue 节点值,返回或设置当前节点的值
元素节点的 nodeValue 始终是 null
父子节点常用属性
• childNodes 只读属性,获取一个节点所有子节点的实时的集合,集合是动态变化的。
• children 只读属性,返回一个节点所有的子元素节点集合,是一个动态更新的 HTML 元素
集合。
• firstChild 只读属性,返回该节点的第一个子节点,如果该节点没有子节点则返回 null。
• lastChild 只读属性,返回该节点的最后一个子节点,如果该节点没有子节点则返回 null。
• parentNode 返回一个当前节点的父节点,如果没有这样的节点,比如说像这个节点是树结构
的顶端或者没有插入一棵树中,这个属性返回 null。
• parentElement 返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个 DOM
元素,则返回 null
兄弟节点常用属性
• nextSibling 只读属性,返回与该节点同级的下一个节点,如果没有返回null。
• previousSibling 只读属性,返回与该节点同级的上一个节点,如果没有返回null。
• nextElementSibling 只读属性,返回与该节点同级的下一个元素节点,如果没有返回null。
• previousElementSibling 只读属性,返回与该节点同级的上一个元素节点,如果没有返回null。
• 注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9以后才支持。
创建新节点的方法
• document.createElement(“div”) 创建元素节点
• document.createAttribute(“id”) 创建属性节点
• document.createTextNode(“hello”) 创建文本节点
• 一般将创建的新节点存在变量中,方便使用。
节点常用操作方法 1
• parentNode.appendChild(child):将一个节点添加到指定父节点的子节点列表末尾。
• parentNode.replaceChild(newChild, oldChild):用指定的节点替换当前节点的一个子节
点,并返回被替换掉的节点。
• parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入一个拥有指定
父节点的子节点,referenceNode 必须设置,如果 referenceElement 为 null 则 newNode
将被插入到子节点的末尾。
• parentNode.removeChild(child):移除当前节点的一个子节点。这个子节点必须存在于当
前节点中。
节点常用操作方法 2
• Node.cloneNode():克隆一个节点,并且可以选择是否克隆这个节点下的所有内容。参数为
Boolean 布尔值,表示是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被
克隆,如果为 false,则只克隆该节点本身,默认值为 true,节点下的内容会被克隆。
• 注意:克隆时,标签上的属性和属性值也会被复制,写在标签行内的绑定事件可以被复制,
但是通过。
节点常用操作方法 3
• Node.hasChildNodes():没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有
子节点。
• Node.contains(child):返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后
代节点。
判断方法总结
• 有三种方法可以判断当前节点是否有子节点。
• node.firstChild !== null
• node.childNodes.length > 0
• node.hasChildNodes()
案例应用
• 动态创建列表
• 动态创建表格
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
90<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> table{ border-collapse: collapse; } thead{ background-color: #ccc; } th,td{ width: 100px; height: 40px; text-align: center; } </style> </head> <body> <h1>动态创建表格</h1> <table id="wrap" border="1"> <thead> <tr> <th>姓名</th> <th>科目</th> <th>成绩</th> <th>操作</th> </tr> </thead> <tbody id="tb"> </tbody> </table> <script src="common.js"></script> <script> // 获取元素 var tb = my$("tb"); // 模拟后台传输的数据 var datas = [ {name: "zs",subject: "语文",score: 80}, {name: "ls",subject: "数学",score: 87}, {name: "ww",subject: "英语",score: 90}, {name: "lb",subject: "物理",score: 89}, {name: "cc",subject: "生物",score: 100}, {name: "sq",subject: "化学",score: 98} ]; // 根据数组中的数据个数生成对应个数的 tr // 将生成 tr 添加到 tbody 中 // 数组遍历 for (var i = 0 ; i < datas.length ; i++) { // 每一个数据都要生成一个 tr var tr = document.createElement("tr"); // 添加到 tb 中 tb.appendChild(tr); // 每一个 tr 中还需要添加对应的 td // 每一行 内部的 td 中的数据来自于 数组的每一项 var data = datas[i]; //{name: "zs",subject: "语文",score: 80} // 遍历 data 对象,根据它的项数来确定添加的 td 的个数 for (var k in data) { // 生成一个 td var td = document.createElement("td"); // 添加到 tr 中去 tr.appendChild(td); // 添加给每一个 td 数据 td.innerText = data[k]; } // 除了前面动态获取的数据 td 之外,还要添加一个删除的 td td = document.createElement("td"); // 添加到 tr 中去 tr.appendChild(td); // 最后一个 td 中需要添加一个 a 标签 var a = document.createElement("a"); a.innerText = "删除"; a.href = "javascript:void(0);" // 将 a 添加到 td 中 td.appendChild(a); // 给生成的每个 a 添加一个点击事件,移除当前所在的行 a.onclick = function () { // 找到所在的行的 tr // this.parentNode.parentNode // 从 tbody 中移除对应的 tr tb.removeChild(this.parentNode.parentNode); }; } </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<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> select { width: 200px; height: 200px; background-color: #33cccc; font-size: 20px; } </style> </head> <body> <select id="all" size="5" multiple="multiple"> <option>苹果</option> <option>橘子</option> <option>梨</option> <option>西瓜</option> <option>水蜜桃</option> </select> <input type="button" value=">>" id="btn1"> <input type="button" value="<<" id="btn2"> <input type="button" value=">" id="btn3"> <input type="button" value="<" id="btn4"> <select id="choose" multiple="multiple"> </select> <script src="common.js"></script> <script> // 获取元素 var all = my$("all"); var choose = my$("choose"); var btn1 = my$("btn1"); var btn3 = my$("btn3"); // 给第一个按钮添加点击事件,让 all 中的所有子元素移动到 choose 中 btn1.onclick = function() { var opts = all.children; //内部的元素时动态添加的 // 获取 all 中所有的子元素 // 获取最开始的数组的个数 var n = opts.length; // console.log(n); // 将所有的 opts 中的元素添加给 choose for (var i = 0; i < n; i++) { choose.appendChild(opts[0]); } }; // 单选移动 btn3.onclick = function() { var opts = all.children; //内部的元素时动态添加的 // 移动的内容希望可以是固定的一个数组中的项 var arr = []; // 通过判断条件,往 arr 中添加需要移动的元素 for (var i = 0; i < opts.length; i++) { if (opts[i].selected === true) { arr.push(opts[i]); } } // 对需要移动的固定数组进行遍历 for (var j = 0; j < arr.length; j++) { choose.appendChild(arr[j]); arr[j].selected = false; } }; </script> </body> </html>
DOM 事件详解
注册事件的其他方法1
• element.addEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:不支持 IE9 以下的浏览器
注册事件的其他方法2
• element.attachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:只支持 IE10 及以下的浏览器。
注册事件的兼容写法
• 自定义一个注册事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 addEventListener 方法
• IE9 以下的浏览器,使用 attachEvent 方法
• 判断浏览器时,不需要判断它的版本,可以检测浏览器能力
• 浏览器能力检测:将某个方法的调用作为 if 语句的判断条件,如果浏览器认识该方法返回
true,否则返回 false。
移除事件的其他方法1
• element.removeEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数引用名
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
• 兼容性问题:不支持 IE9以下的浏览器
移除事件的其他方法2
• element.detachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
兼容性问题:只支持 IE10 及以下的浏览器
移除事件的兼容写法
• 自定义一个移除事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 removeEventListener 方法
• IE9 以下的浏览器,使用 detachEvent 方法
• 建议:将自己封装的一些常用函数和方法,放到一个单独的 .js 文件中
DOM 事件流
事件流的三个阶段
• 第一个阶段:事件捕获
• 第二个阶段:事件执行过程
• 第三个阶段:事件冒泡
• addEventListener() 第三个参数为 false 时,事件冒泡
• addEventListener() 第三个参数为 true 时,事件捕获
• onclick 类型:只能进行事件冒泡过程,没有捕获阶段
• attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
事件委托
• 利用事件冒泡,将子级的事件委托给父级加载
• 同时,需要利用事件函数的一个 e 参数,内部存储的是事件对象
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<!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>Document</title> <style> * { margin: 0; padding: 0; } ul { width: 300px; border: 1px dashed #f0f; margin: 50px auto; font-size: 24px; line-height: 48px; list-style: none; } li { padding-left: 20px; cursor: pointer; } </style> </head> <body> <ul id="list"> <li>刘亦菲</li> <li>杨幂</li> <li>唐嫣</li> <li>赵丽颖</li> <li>刘诗诗</li> </ul> <script> // 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加 // 以前的思路:获取所有的 li 标签元素,批量添加事件 // 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源 // 获取元素 var list = document.getElementById("list"); var lis = list.children; // 给 ul 添加点击事件 list.onclick = function (e) { // 在内部要想办法找到真正触发事件的 li // 借用事件函数内部的一个参数 e,e 是事件对象 // 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据 // e.target 属性记录的就是真正触发事件的事件源 // 排除其他 for (var i = 0 ; i < lis.length ; i++) { lis[i].style.backgroundColor = ""; } e.target.style.backgroundColor = "pink"; }; </script> </body> </html>
事件对象
• 只要触发事件,就会有一个对象,内部存储了与事件相关的数据。
• e 在低版本浏览器中有兼容问题,低版本浏览器使用的是 window.event
• 事件对象常用的属性:
e.eventPhase 查看事件触发时所处的阶段
e.target 用于获取触发事件的元素
e.srcElement 用于获取触发事件的元素,低版本浏览器使用
e.currentTarget 用于获取绑定事件的事件源元素
e.type 获取事件类型
e.clientX/e.clientY 所有浏览器都支持,鼠标距离浏览器窗口左上角的距离
e.pageX/e.pageY IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离
案例
• 图片跟随鼠标移动效果
取消默认行为和阻止事件传播的方式
• e.preventDefault() 取消默认行为
• e.returnValue 取消默认行为,低版本浏览器使用
• e.stopPropagation(); 阻止冒泡,标准方式
• e.cancelBubble = true; 阻止冒泡,IE 低版本,标准中已废弃
其他事件类型
• MDN web 事件参考:https://developer.mozilla.org/zh-CN/docs/Web/Events
DOM 特效
DOM 提供了一套与元素自身有关的位置
和大小的属性。
偏移量属性
• offsetParent 偏移参考父级,距离自己最近的有定位的父级,如果都没有定位参考body(html)
• offsetLeft/offsetTop 偏移位置
• offsetWidth/offsetHeight 偏移大小
客户端大小
• client 系列没有参考父级元素。
• clientLeft/clientTop 边框区域尺寸,不常用
• clientWidth/clientHeight 边框内部大小
滚动偏移属性
• scrollLeft/scrollTop 盒子内部滚动出去的尺寸
• scrollWidth/scrollHeight 盒子内容的宽度和高度
案例
• 拖拽案例
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } .nav { height: 30px; background: #036663; border-bottom: 1px solid #369; line-height: 30px; padding-left: 30px; } .nav a { color: #fff; text-align: center; font-size: 14px; text-decoration: none; } .d-box { width: 400px; height: 300px; border: 5px solid #eee; box-shadow: 2px 2px 2px 2px #666; position: absolute; top: 40%; left: 40%; background-color: white; /* 不让文字被选中 */ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .hd { width: 100%; height: 25px; background-color: #7c9299; border-bottom: 1px solid #369; line-height: 25px; color: white; cursor: move; } #box_close { float: right; cursor: pointer; } </style> </head> <body> <div class="nav"> <a href="javascript:;" id="register">注册信息</a> </div> <div class="d-box" id="d_box"> <div class="hd" id="drop">注册信息 (可以拖拽) <span id="box_close">【关闭】</span> </div> <div class="bd"></div> </div> <script src="common.js"></script> <script> // 获取元素 var box = document.getElementById("d_box"); var drop = document.getElementById("drop"); var close = document.getElementById("box_close"); // 给 drop 添加鼠标按下事件,在内部继续绑定一个鼠标移动事件 drop.onmousedown = function(e) { e = e || window.event; // 记忆鼠标按下时,鼠标在父盒子内部的间距 var l = e.pageX - box.offsetLeft; var t = e.pageY - box.offsetTop; // 鼠标移动事件 drop.onmousemove = function(e) { e = e || window.event; // 鼠标移动过程中,可以计算 box 的 left 和 top var nowleft = e.pageX - l; var nowtop = e.pageY - t; // 赋值给 box 的样式属性 box.style.left = nowleft + "px"; box.style.top = nowtop + "px"; }; }; // 鼠标弹起事件 drop.onmouseup = function() { drop.onmousemove = null; }; // 点击 关闭 box close.onclick = function() { box.style.display = "none"; }; </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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> .login-header { width: 100%; text-align: center; height: 30px; font-size: 24px; line-height: 30px; } ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a { padding: 0px; margin: 0px; } .login { width: 512px; position: absolute; border: #ebebeb solid 1px; height: 280px; left: 50%; right: 50%; background: #ffffff; box-shadow: 0px 0px 20px #ddd; z-index: 9999; margin-left: -256px; margin-top: 140px; display: none; } .login-title { width: 100%; margin: 10px 0px 0px 0px; text-align: center; line-height: 40px; height: 40px; font-size: 18px; position: relative; cursor: move; -moz-user-select: none; /*火狐*/ -webkit-user-select: none; /*webkit浏览器*/ -ms-user-select: none; /*IE10*/ -khtml-user-select: none; /*早期浏览器*/ user-select: none; } .login-input-content { margin-top: 20px; } .login-button { width: 50%; margin: 30px auto 0px auto; line-height: 40px; font-size: 14px; border: #ebebeb 1px solid; text-align: center; } .login-bg { width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; background: #000000; filter: alpha(opacity=30); -moz-opacity: 0.3; -khtml-opacity: 0.3; opacity: 0.3; display: none; } a { text-decoration: none; color: #000000; } .login-button a { display: block; } .login-input input.list-input { float: left; line-height: 35px; height: 35px; width: 350px; border: #ebebeb 1px solid; text-indent: 5px; } .login-input { overflow: hidden; margin: 0px 0px 20px 0px; } .login-input label { float: left; width: 90px; padding-right: 10px; text-align: right; line-height: 35px; height: 35px; font-size: 14px; } .login-title span { position: absolute; font-size: 12px; right: -20px; top: -30px; background: #ffffff; border: #ebebeb solid 1px; width: 40px; height: 40px; border-radius: 20px; } </style> </head> <body> <div class="login-header"><a id="link" href="javascript:void(0);">点击,弹出登录框</a></div> <div id="login" class="login"> <div id="title" class="login-title">登录会员 <span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span> </div> <div class="login-input-content"> <div class="login-input"> <label>用户名:</label> <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input"> </div> <div class="login-input"> <label>登录密码:</label> <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input"> </div> </div> <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div> </div> <!-- 遮盖层 --> <div id="bg" class="login-bg"></div> <script> // 获取元素 var link = document.getElementById("link"); var login = document.getElementById("login"); var bg = document.getElementById("bg"); var closeBtn = document.getElementById("closeBtn"); // 添加 link 的点击事件,让登录窗口和遮盖层显示 link.onclick = function () { login.style.display = "block"; bg.style.display = "block"; }; // 添加 btn 的点击事件,让登录窗口和遮盖层隐藏 closeBtn.onclick = function () { login.style.display = "none"; bg.style.display = "none"; }; </script> </body> </html>
最后
以上就是害羞翅膀最近收集整理的关于DOM——文档对象模型的全部内容,更多相关DOM——文档对象模型内容请搜索靠谱客的其他文章。
发表评论 取消回复