什么是DOM

  • DOM,全称Document Object Model文档对象模型
  • JS中通过DOM来对HTML文档进行操作。只要了解了DOM就可以随心所欲的操作WEB页面
  • 文档
    • 文档表示的就是整个HTML网页文档
  • 对象
    • 对象表示将网页中的每一个部分都转换为了一个对象
  • 模型
    • 使用模型来表示对象之间的关系,这样方便我们获取对象

image-20210508211556802

简例

  • 浏览器已经为我们提供了文档节点对象,这个对象是window属性

    可以在页面中直接使用,文档节点代表的是整个网页

1
2
3
4
5
6
7
8
<button id="btn">我是一个按钮</button>
<script>
//获取到button对象
var btn = document.getElementById("btn");
console.log(btn.innerHTML);
//修改按钮的文字
btn.innerHTML = "I'm Button";
</script>

输出结果为:

image-20210508212848166

事件

  • 事件,就是用户和浏览器之间的交互行为

    • 比如:点击按钮,鼠标移动,关闭窗口……
  • 我们可以在事件对应的属性中设置一些JS代码

  • 当这些事件被触发时,这些代码将会执行

  • <button id="btn" onmousemove="alert('讨厌,你点我干嘛!')">我是一个按钮</button>

    这种写法我们称为结构和行为耦合,不方便维护,不推荐使用

  • 可以为按钮的对应事件绑定处理函数的形式来响应事件

    • 这样当事件被触发时,其对应的函数将会被调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <button id="btn">我是一个按钮</button>
    <script>
    //获取到button对象
    var btn = document.getElementById("btn");
    //绑定一个单击事件
    //像这种为单击事件绑定的函数,我们称之为单击响应函数
    btn.onclick = function(){
    alert("你还点~~~");
    }
    </script>

文档的加载

  • 浏览器在加载页面时,是按照自上向下的顺序加载的

  • 读取到一行就运行一行,如果将script标签写到页面的上面

    在执行代码时,页面还没有加载,DOM对象也没有加载

    会导致无法获取到DOM对象

  1. 将JS代码编写到下面就是为了可以在页面加载完毕以后再执行代码

  2. onload事件会在整个页面加载完成后才触发

    这样可以确保代码执行时,所有的DOM对象都已经加载完毕了

1
2
3
4
5
6
7
8
9
<script>
//为window绑定一个onload事件
window.onload = function(){
var btn = document.getElementById("btn");
btn.onclick = function(){
alert("你还点~~~");
}
}
</script>
  • 最优的解决方法是1,性能!!!用户体验!!!(其实差别不是太大)

DOM查询

获取元素节点

  • 通过document对象调用
  1. getElementById()

    • 通过id属性获取一个元素节点对象
  2. getElementsByTagName()

    • 通过标签名获取一组元素节点对象
    • 这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中
    • 即使查询到的元素只有一个,也会封装到数组中并返回
  3. getElementsByName()

    • 通过name属性获取一组元素节点对象

    • 如果需要读取元素节点属性:

      直接使用 元素.属性名

      例子:元素.id 元素.name 元素.value

      注意:class属性不能采用这种方式

      读取class属性时需要使用 元素.className

图片切换练习

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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}

img{
width: 500px;
height: 300px;
}

#outer{
width: 500px;
margin: 50px auto;
padding: 20px;
text-align: center;
background-color: greenyellow;
border-radius: 20px;
}
</style>
<script>
window.onload = function(){
/*
*点击按钮切换图片
*/
//获取两个按钮
var prev = document.getElementById("prev");
var next = document.getElementById("next");

//要切换图片就是要修改img标签的src属性
var img = document.getElementsByTagName("img")[0];
//创建一个数组,用来保存图片的路径
var imgArr = ["img/1.jpg" , "img/2.jpg","img/3.jpg","img/4.jpg","img/5.jpg",];
//创建一个变量,用来保存当前正在显示的图片的索引
var index = 0;

//获取id为info的p元素
var info = document.getElementById("info");
//设置提示文字
info.innerHTML = "一共" + imgArr.length + "张图片,当前第" + (index+1) + "张";

//分别为两个按钮绑定单击响应函数
prev.onclick = function(){
//切换到上一张,index自减
index--;

if(index < 0){
index = imgArr.length-1;
}

img.src = imgArr[index];

//每次点击之后,重新设置信息
info.innerHTML = "一共" + imgArr.length + "张图片,当前第" + (index+1) + "张";

};
next.onclick = function(){
//切换到下一张,index自增
index++;

if(index > imgArr.length-1){
index = 0;
}

img.src = imgArr[index];

//每次点击之后,重新设置信息
info.innerHTML = "一共" + imgArr.length + "张图片,当前第" + (index+1) + "张";
};

}
</script>
</head>
<body>
<div id="outer">
<p id="info"></p>
<img src="img/1.jpg" alt="二次元">
<button id="prev">上一张</button>
<button id="next">下一张</button>
</div>
</body>
</html>

输出结果为:

image-20210510215208181

获取元素节点的子节点

  • 通过具体的元素节点调用
  1. getElementsByTagName()
    • 方法,返回当前节点的指定标签名后代节点
  2. childNodes
    • 属性,表示当前节点的所有子节点
    • 会获取包含文本节点在内的所有子节点
    • DOM标签间的空白也会当成文本节点
  3. firstChild
    • 属性,表示当前节点的第一个子节点(包括空白文本节点)
  4. lastChild
    • 属性,表示当前节点的最后一个子节点(包括空白文本节点)
  5. children
    • 属性,可以获取当前元素的所有子元素(更推荐使用)

获取父节点和兄弟节点

  • 通过具体的节点调用
  1. parentNode
    • 属性,表示当前节点的父节点
  2. previousSibling
    • 属性,表示当前节点的前一个兄弟节点
  3. nextSibling
    • 属性,表示当前节点的后一个兄弟节点

全选练习

在事件的响应函数中,响应函数是给谁绑定的,this就是谁

代码如下:

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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
//获取四个多选框items
var items = document.getElementsByName("items");
var checkedAllBox = document.getElementById("checkedAllBox");

//全选按钮
var checkedAllBtn = document.getElementById("checkedAllBtn");
checkedAllBtn.onclick = function(){
//遍历items
for (let i = 0; i < items.length; i++) {
//设置四个多选框变为选中状态
items[i].checked = true;
}

//将全选,全不选设置为选中
checkedAllBox.checked = true;
}
//全不选按钮
var checkedNoBtn = document.getElementById("checkedNoBtn");
checkedNoBtn.onclick = function () {
for (let i = 0; i < items.length; i++) {
items[i].checked = false;
}
//将全选,全不选设置为不选中
checkedAllBox.checked = false;
}
//反选按钮
var checkedRevBtn = document.getElementById("checkedRevBtn");
checkedRevBtn.onclick = function(){
for (let i = 0; i < items.length; i++) {
/* if(items[i].checked){
items[i].checked = false;
}else{
items[i].checked = true;
}
*/
//更简单的写法:
items[i].checked = !items[i].checked;
}
//将checkedAllBox设置为选中状态
checkedAllBox.checked = true;
for (let j = 0; j < items.length; j++) {
//只要有一个没选中就不是全选
if(!items[j].checked){
checkedAllBox.checked = false;
break;
}
}

}

//提交按钮
//点击按钮后,将所有选中的多选框的value属性值弹出
var sendBtn = document.getElementById("sendBtn");
sendBtn.onclick = function(){
for (let i = 0; i < items.length; i++) {
if(items[i].checked == true){
alert(items[i].value);
}
}
}
//全选,全不选 多选框
checkedAllBox.onclick = function() {
for (let i = 0; i < items.length; i++) {
items[i].checked = this.checked;
}
}
//checkedAllBox与四个多选框同步
for (let i = 0; i < items.length; i++) {
items[i].onclick = function() {
//将checkedAllBox设置为选中状态
checkedAllBox.checked = true;
for (let j = 0; j < items.length; j++) {
//只要有一个没选中就不是全选
if(!items[j].checked){
checkedAllBox.checked = false;
break;
}
}
}
}
}
</script>
</head>
<body>
<form action="">
你爱好的运动是?
<input type="checkbox" id="checkedAllBox">全选/全不选
<br>
<input type="checkbox" name="items" value="足球">足球
<input type="checkbox" name="items" value="篮球">篮球
<input type="checkbox" name="items" value="羽毛球">羽毛球
<input type="checkbox" name="items" value="乒乓球">乒乓球
<br>
<input type="button" id="checkedAllBtn" value="全 选">
<input type="button" id="checkedNoBtn" value="全不选">
<input type="button" id="checkedRevBtn" value="反 选">
<input type="button" id="sendBtn" value="提 交">
</form>
</body>
</html>

输出结果为:

image-20210511233919405

DOM查询的其它方法

  • 在document中有一个属性body,它保存的是body的引用

    var body = document.body;

  • document.documentElement; 保存的是html根标签

  • document.all 代表页面中所有元素

  • 根据元素的class属性值查询一组元素节点对象

    (不兼容IE8及以下浏览器)

    var box1 = document.getElementsByClassName("box1");

  • document.querySelector();

    需要一个选择器的字符串作为参数,可以根据一个CSS选择器来查询一个元素节点对象

    var div = document.querySelector(".box1 div"); 会选中类名为box1下的div对象

    使用该方法只会返回唯一一个元素,如果满足条件的元素有多个,那么它只会返回第一个

  • document.querySelectorAll();

    该方法与querySelector()用法类似

    不同的是它会将符合条件的元素封装到一个数组中返回

DOM增删改

  • 创建元素节点对象

    document.createElement();

    他需要一个标签名作为参数,将会根据该标签名创建元素节点对象

    并将创建好的对象作为返回值返回

    创建一个<li>var li = document.createElement("li");

  • 创建文本节点对象

    document.createTextNode();

    可以用于创建一个文本节点对象

    需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回

    例:var Text = document.createTextNode("广州");

  • 把新的子节点添加到指定节点

    appendChild()

    • 向一个父节点中添加一个新的子节点

      父节点.appendChild(子节点);

      li.appendChild(Text)

  • 在指定的子节点前面插入新节点

    insertBefore()

    父节点.insertBefore(新节点,旧节点);

  • 替换子节点

    replaceChild()

    父节点.replaceChild(新节点,旧节点);

  • 删除子节点

    removeChild()

    父节点.removeChild(子节点);

    更简单的方法:子节点.parentNode.removeChild(子节点);

  • 读取某节点内的HTML代码

    节点.innerHTML

  • 使用innerHTML也可以完成DOM的增删改的相关操作

    例:city.innerHTML += "<li>广州</li>";

添加删除记录练习

代码如下:

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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#employeeTable tr,#employeeTable td,#employeeTable th{
border: 2px solid black;
}
#employeeTable{
margin-top: 100px;
}
table{
border-collapse: collapse;
text-align: center;
margin: 0px auto;
}
#formDiv{
display: inline-block;
border: 2px solid black;
padding: 10px;
position: relative;
left: 50%;
transform: translate(-50%,50px);
}
</style>
</head>
<body>
<table id="employeeTable">
<tr>
<th>Name</th>
<th>Email</th>
<th>Salary</th>
<th>&nbsp;</th>
</tr>
<tr>
<td>Tom</td>
<td>tom@tom.com</td>
<td>5000</td>
<td><a href="deleteEmp?id=001">Delete</a></td>
</tr>
<tr>
<td>Jerry</td>
<td>jerry@sohu.com</td>
<td>8000</td>
<td><a href="deleteEmp?id=002">Delete</a></td>
</tr>
<tr>
<td>Bob</td>
<td>bob@tom.com</td>
<td>10000</td>
<td><a href="deleteEmp?id=003">Delete</a></td>
</tr>
</table>

<script>
function delA(){
var tr = this.parentNode.parentNode;
//删除前弹出一个提示框
var flag = confirm("确认删除" + tr.getElementsByTagName("td")[0].innerHTML + "吗?");
if(flag){
tr.parentNode.removeChild(tr);
}

//点击超链接后,超链接会跳转页面,这个是超链接的默认行为
//可以通过在响应函数的最后return false来取消默认行为
return false;
}
//获取所有的超链接
var allA = document.getElementsByTagName("a");
//为每个超链接都绑定一个单击响应函数
for (let i = 0; i < allA.length; i++) {
allA[i].onclick = delA;
}
window.onload = function(){
//添加员工功能
var addEmpButton = document.getElementById("addEmpButton");
addEmpButton.onclick = function(){
//获取新员工信息
var name = document.getElementById("empName").value;
var email = document.getElementById("email").value;
var salary = document.getElementById("salary").value;
var tr = document.createElement("tr");
tr.innerHTML = "<td>"+name+"</td>"+
"<td>"+email+"</td>"+
"<td>"+salary+"</td>"+
"<td><a href='javascript:;'>Delete</a></td>";
var tbody = document.getElementsByTagName("tbody")[0];
tbody.appendChild(tr);
var a = tr.getElementsByTagName("a")[0];
a.onclick = delA;
}
}
</script>

<div id="formDiv">
<h3>添加新成员</h3>
<table>
<tr>
<td class="word">name:</td>
<td class="inp">
<input type="text" name="empName" id="empName">
</td>
</tr>
<tr>
<td class="word">email:</td>
<td class="inp">
<input type="text" name="email" id="email">
</td>
</tr>
<tr>
<td class="word">salary</td>
<td class="inp">
<input type="text" name="salary" id="salary">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="addEmpButton">
Submit
</button>
</td>
</tr>
</table>
</div>
</body>
</html>

输出结果如图:

image-20210515113859891

亲自试一试:添加删除记录练习