一、概述

1.1、什么是DOM

​ 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口

​ W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。

1.2、DOM 树

0082

  • 文档:一个页面就是一个文档,DOM 中使用 document 表示
  • 元素:页面中的所有标签都是元素,DOM 中使用 element 表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示

二、获取元素

2.1、概述

​ DOM在我们实际开发中主要用来操作元素。我们如何来获取页面中的元素呢?

​ 获取页面中的元素可以使用以下几种方式:

  • 根据 ID 获取
  • 根据标签名获取
  • 根据name名称获取
  • 通过 HTML5 新增的方法获取
  • 特殊元素获取

2.2、根据ID获取

​ 使用 getElementById() 方法可以获取带有 ID 的元素对象。

1
2
3
4
5
6
7
8
9
10
11
<body>
<div id="myDiv">HelloWorld</div>
<script>
var divObj = document.getElementById("myDiv");
console.log(divObj);
console.log(typeof divObj); // 返回的结果是一个对象

// 使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法
console.dir(divObj);
</script>
</body>

2.3、根据标签名获取

​ 使用getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<ul>
<li>HTML</li>
<li>JavaScript</li>
<li>CSS3</li>
</ul>

<script>
var liObjs = document.getElementsByTagName("li");
console.log(liObjs); // 返回的是元素对象的集合 以伪数组的形式存储的

// 遍历
for (var i = 0; i < liObjs.length; i++) {
console.log(liObjs[i]);
}
</script>
</body>
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
<body>
<ul>
<li>HTML</li>
<li>JavaScript</li>
<li>CSS3</li>
</ul>
<ol>
<li>Vue</li>
<li>React</li>
</ol>
<script>
// 需求:我想获取ol标签里面的li

// >> 第一步: 先获取ol, 注意返回过来的是一个数组
var olObjs = document.getElementsByTagName("ol");

// >> 第二步:再根据获取的olObjs[0]获取里面的所有的li
var liObjs = olObjs[0].getElementsByTagName("li");

// 遍历
for (var i = 0; i < liObjs.length; i++) {
console.log(liObjs[i]);
}
</script>
</body>

2.4、根据name名称获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
跳舞: <input type="checkbox" name="hobby">
唱歌: <input type="checkbox" name="hobby">
学习: <input type="checkbox" name="hobby">

<script>
var hobbyObjs = document.getElementsByName("hobby");

// 遍历
for (var i = 0; i < hobbyObjs.length; i++) {
console.log(hobbyObjs[i]);
}
</script>
</body>

2.5、通过 HTML5 新增的方法获取

2.5.1、根据类名获得某些元素集合

​ 方法:getElementsByClassName

1
2
3
4
5
6
7
8
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<script>
var boxObjs = document.getElementsByClassName("box");
console.log(boxObjs);
</script>
</body>

2.5.2、根据指定选择器返回第一个元素对象

​ 方法:querySelector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 页面上有两个类为box的div元素,但是只会获取第一个
var boxObj = document.querySelector(".box");
console.log(boxObj);

// 页面上有两个标签名为li的元素,但是只会获取第一个
var liObj = document.querySelector("li");
console.log(liObj);
</script>
</body>

2.5.3、根据指定选择器返回所有元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 获取页面上所有的类名为box的div元素
var boxObjs = document.querySelectorAll(".box");
console.log(boxObjs);

// 获取页面上所有的标签为li的元素
var liObjs = document.querySelectorAll("li");
console.log(liObjs);
</script>
</body>

2.6、特殊元素获取

2.6.1、获取body 元素

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<script>
// 获取body元素

// >> 方式一, 简单
var bodyObj1 = document.body;
console.log(bodyObj1);

// >> 方式二
var bodyObj2 = document.getElementsByTagName("body")[0];
console.log(bodyObj2);
</script>
</body>

2.6.2、获取html 元素

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<script>
// 获取html元素

// >> 方式一, 简单
var htmlObj1 = document.documentElement;
console.log(htmlObj1);

// >> 方式二
var htmlObj2 = document.getElementsByTagName("html")[0];
console.log(htmlObj2);
</script>
</body>

三、事件基础

3.1、概述

​ 网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。

3.2、事件三要素

  1. 事件源 (谁,指的是事件被触发的对象 )

  2. 事件类型 (什么事件,指的是鼠标点击、还是鼠标经过、还是键盘按下)

  3. 事件处理程序 (做啥, 通过一个函数赋值的方式完成一个功能)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<button id="btn">点我</button>
<script>
// 需求: 点击一个按钮,弹出一个对话框

// >> 第一步: 获取事件源
var btnObj = document.getElementById("btn");
// >> 第二步: 绑定事件
// btnObj.onclick
// >> 第三步:添加事件处理程序
btnObj.onclick = function() {
alert("按钮被点击了...");
}
</script>
</body>

3.3、常见的鼠标事件

0083

四、操作元素

4.1、概述

​ JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内

容 、属性等。注意以下都是属性。

4.2、改变/获取元素内容

  • innerHTML
  • innerText
1
2
3
4
5
6
7
8
9
<body>
<div id="myDiv">HelloWorld</div>
<script>
// 获取div的内容
var divObj = document.getElementById("myDiv");
console.log(divObj.innerHTML);
console.log(divObj.innerText);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<button id="btn1">通过innertHTML改变div内容</button>
<button id="btn2">通过innertText改变div内容</button>

<div id="myDiv">HelloWorld</div>
<script>
// 获取div元素对象
var divObj = document.getElementById("myDiv");

// 获取两个按钮
var btn1Obj = document.getElementById("btn1");
var btn2Obj = document.getElementById("btn2");

btn1Obj.onclick = function() {
divObj.innerHTML = "<h1>JavaScript</h1>"
}

btn2Obj.onclick = function() {
divObj.innerText = "<h1>JavaScript</h1>"
}
</script>
</body>

4.3、常用元素的属性操作

0084

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<button id="ldh">刘德华</button>
<button id="zxy">张学友</button> <br>
<img src="images/ldh.jpg" alt="" title="刘德华">
<script>
// 获取两个按钮
var btn1Obj = document.getElementById("ldh");
var btn2Obj = document.getElementById("zxy");

// 获取img标签对象
var imgObj = document.querySelector("img");

btn1Obj.onclick = function() {
imgObj.src = "images/ldh.jpg";
}

btn2Obj.onclick = function() {
imgObj.src = "images/zxy.jpg";
}
</script>
</body>

4.4、表单元素的属性操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<button>按钮</button>
<input type="text" value="用户名">
<script>
// 点击按钮,修改输入框的值,并且将按钮禁用

// >> 获取按钮元素对象
var btnObj = document.querySelector("button");
// >> 获取input元素对象
var inputObj = document.querySelector("input");
// >> 按钮绑定事件
btnObj.onclick = function() {
// 修改文本框的内容
inputObj.value = '张三';
// 按钮禁用
this.disabled = true;
}
</script>
</body>

4.5、样式属性操作

4.5.1、说明

​ 我们可以通过 JS 修改元素的大小、颜色、位置等样式。

0085

注意

  • JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
  • JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高

4.5.2、行内样式操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<head>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
// 点击div元素,背景颜色变为红色,宽度变大

// >> 1、获取div元素对象
var divObj = document.querySelector("div");
// >> 2、绑定事件处理程序
divObj.onclick = function() {
this.style.backgroundColor = 'red'; // 采用驼峰命名法
this.style.width = '500px';
}
</script>
</body>
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
<head>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<button>隐藏</button>
<script>
// 点击按钮让div能够显示或者隐藏

// >> 1、获取div元素
var divObj = document.querySelector("div");
// >> 2、获取button元素对象
var buttonObj = document.querySelector("button");
// >> 3、绑定事件处理程序
var flag = true; // 表示div显示
buttonObj.onclick = function() {
if (flag) {
// true表示显示则隐藏
divObj.style.display = 'none';
flag = false;
this.innerHTML = '显示'
} else {
divObj.style.display = 'block';
flag = true;
this.innerHTML = '隐藏'
}
}
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<input type="text" value="搜索你想要的内容呗">
<script>
// 当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。

// >> 1、获取input元素
var inputObj = document.querySelector("input");
// >> 2、绑定事件处理程序
// >>>> 获得焦点事件 onfocus
inputObj.onfocus = function() {
if (this.value === '搜索你想要的内容呗') {
this.value = '';
}
};
// >>>> 失去焦点事件 onblur
inputObj.onblur = function() {
if (this.value === '') {
this.value = '搜索你想要的内容呗';
}
};
</script>
</body>

4.5.3、类名样式操作

1
2
3
4
# 使用场景
1. 如果样式修改较多,可以采取操作类名方式更改元素样式。
2. class因为是个保留字,需要使用className来操作元素类名属性
3. 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
<head>
<style>
.first {
width: 200px;
height: 200px;
background-color: pink;
margin-top: 100px;
}

.newChangeStyle {
width: 300px;
height: 300px;
background-color: red;
color: blue;
}
</style>
</head>
<body>
<div class="first">HelloWorld</div>
<script>
// 点击div,设置背景颜色,高度,宽度,字体颜色

// 1、获取div元素
var divObj = document.querySelector("div");
// 2、注册事件
divObj.onclick = function() {
// 通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
// this.className = 'newChangeStyle';

// 注: 这种方式把原先的类名也给覆盖了,如果想保留,可以这样
this.className = 'first newChangeStyle';
};
</script>
</body>

4.6、总结

1
# 操作元素是DOM的核心内容

0086

4.7、排他思想

4.7.1、需求

0087

​ 如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:

  • 所有元素全部清除样式(干掉其他人)
  • 给当前元素设置样式 (留下我自己)
  • 注意顺序不能颠倒,首先干掉其他人,再设置自己
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// 点击某个button,设置被点击button的背景颜色

// 1、获取所有的button元素对象
var buttonObjs = document.querySelectorAll("button");
// 2、循环遍历注册事件
for (var i = 0; i < buttonObjs.length; i++) {
buttonObjs[i].onclick = function() {
// 第一步:我们先把所有的按钮背景颜色去掉 干掉所有人
for (var j = 0; j < buttonObjs.length; j++) {
buttonObjs[j].style.backgroundColor = '';
}
// 第二步:设置当前的元素背景颜色为红色 留下我自己
this.style.backgroundColor = 'red';
}
}
</script>
</body>

4.7.2、案例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
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
<body>
<table border="1px">
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新公布净值</th>
<th>累计净值</th>
<th>前单位净值</th>
<th>净值增长率</th>
</tr>
</thead>
<tbody>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
</tbody>
</table>
<script>
// 鼠标移动到表格的某一行,修改该行的背景颜色

// 1、获取tbody里面所有的tr行
var trObjs = document.querySelector("tbody").querySelectorAll("tr");
// 2、为每一个行绑定事件
for (var i = 0; i < trObjs.length; i++) {
trObjs[i].onmouseover = function() {
// 第一步:我们先把所有的按钮背景颜色去掉 干掉所有人
for (var j = 0; j < trObjs.length; j++) {
trObjs[j].style.backgroundColor = '';
}
// 第二步:设置当前的元素背景颜色为红色 留下我自己
this.style.backgroundColor = 'red';
}
}
</script>
</body>
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
<body>
<table border="1px">
<thead>
<tr>
<th>代码</th>
<th>名称</th>
<th>最新公布净值</th>
<th>累计净值</th>
<th>前单位净值</th>
<th>净值增长率</th>
</tr>
</thead>
<tbody>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金穗3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.074</td>
<td>+0.047%</td>
</tr>
</tbody>
</table>
<script>
// 鼠标移动到表格的某一行,修改该行的背景颜色

// 1、获取tbody里面所有的tr行
var trObjs = document.querySelector("tbody").querySelectorAll("tr");
// 2、为每一个行绑定事件
for (var i = 0; i < trObjs.length; i++) {
trObjs[i].onmouseover = function() {
this.style.backgroundColor = 'red';
}
trObjs[i].onmouseout = function() {
this.style.backgroundColor = '';
}
}
</script>
</body>

4.7.3、案例2

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
<body>
全选:<input type="checkbox" id="checkAll" /> <br/>
唱歌: <input type="checkbox" name="hobby" /> <br/>
跳舞: <input type="checkbox" name="hobby" /> <br/>
学习: <input type="checkbox" name="hobby" /> <br/>
打游戏: <input type="checkbox" name="hobby" /> <br/>

<script>
// >> 获取全选按钮
var checkAllObj = document.getElementById("checkAll");
// >> 获取所有的爱好复选框
var hobbyObjs = document.getElementsByName("hobby");

// 全选和取消全选做法:让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
checkAllObj.onclick = function() {
for (var i = 0; i < hobbyObjs.length; i++) {
hobbyObjs[i].checked = this.checked;
}
}

// 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环 查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
for (var i = 0; i < hobbyObjs.length; i++) {
hobbyObjs[i].onclick = function() {
var flag = true; // 表示都选中了
// 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
for (var j = 0; j < hobbyObjs.length; j++) {
if (!hobbyObjs[j].checked) {
flag = false; // 一旦发现有没有选中的,则标记为false
break;
}
}
checkAllObj.checked = flag;
}
}
</script>
</body>

4.8、自定义属性的操作

4.8.1、获取属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<div id="myDiv"></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 获取属性方式一: element.属性
console.log(divObj.id);

// >> 获取属性方式二: element.getAttribute('属性')
console.log(divObj.getAttribute("id"));
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<div index="1"></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 获取属性方式一: element.属性
console.log(divObj.index); // undefined

// >> 获取属性方式二: element.getAttribute('属性')
console.log(divObj.getAttribute("index"));
</script>
</body>
1
2
3
# 总结
1. element.属性 获取内置属性值(元素本身自带的属性)
2. element.getAttribute(‘属性’); 主要获得自定义的属性 (标准) 我们程序员自定义的属性

4.8.2、设置属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 设置属性方式一: element.属性 = 值
divObj.id = 'myDiv';
divObj.className = 'content';

// >> 设置属性方式二: element.setAttribute('属性',值)
divObj.setAttribute('style', 'width:200px');
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<div></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 设置属性方式一: element.属性 = 值
divObj.index = 1; // 不能添加index属性

// >> 设置属性方式二: element.setAttribute('属性',值)
divObj.setAttribute('index2', 2);
</script>
</body>
1
2
3
# 总结
1、element.属性 设置内置属性值
2、element.setAttribute(‘属性’); 主要设置自定义的属性 (标准)

4.8.3、移除属性

1
2
3
4
5
6
7
8
9
10
<body>
<div index="1">ss</div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 移除属性
divObj.removeAttribute("index");
</script>
</body>

4.9、H5自定义属性

4.9.1、说明

1
2
3
4
1. 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
2. 自定义属性获取是通过getAttribute(‘属性’) 获取。
3. 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
4. H5给我们新增了自定义属性:

4.9.2、设置H5自定义属性

​ H5规定自定义属性是这样的:data-开头做为属性名并且赋值。

​ 比如 <div data-index="1"></div> ,或者使用 JS 设置 element.setAttribute(‘data-index’, 2)

1
2
3
4
5
6
7
8
9
10
<body>
<div></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 设置属性
divObj.setAttribute("data-index", 1);
</script>
</body>

4.9.3、获取H5自定义属性

1
2
3
# 两种方式
1. 兼容性获取 element.getAttribute(‘data-index’);
2. H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div></div>
<script>
// 获取div元素对象
var divObj = document.querySelector("div");

// >> 设置属性
divObj.setAttribute("data-index", 1);

// >> 获取属性值方式一
console.log(divObj.getAttribute("data-index"));

// >> 获取属性方式二
console.log(divObj.dataset.index);
console.log(divObj.dataset['index']);
</script>
</body>

五、节点操作

5.1、说明

​ 其实对于获取元素节点,一般来说有两种方式:

0088

5.2、概述

​ 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。

​ HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以

创建或删除。

0089

​ 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个

基本属性。

  • 元素节点 nodeType 为 1
  • 属性节点 nodeType 为 2
  • 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)

​ 我们在实际开发中,节点操作主要操作的是元素节点

1
1. 利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。

5.3、节点层级

5.3.1、父级节点

1
2
3
4
5
# 获取方式
node.parentNode
# 说明
1. parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
2. 如果指定的节点没有父节点则返回 null
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<div>
<div id="parent">
<div id="child">HelloWorld</div>
</div>
</div>
<script>
// 得到子节点
var childObj = document.querySelector("#child");
// 获取父节点
console.log(childObj.parentNode.id);
</script>
</body>

5.3.2、子级节点

5.3.2.1、方式一

1
2
3
4
5
6
# 方式
parentNode.childNodes(标准)
# 说明
1. 返回包含指定节点的子节点的集合
2. 返回值里面包含了所有的子节点,包括元素节点,【文本节点】等
3. 如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>

</ul>
<script>
// 得到父元素节点
var ulObj = document.querySelector("ul");
// 获取ul节点下面所有的子节点li
console.log(ulObj.childNodes); // NodeList(9)
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>

</ul>
<script>
// 得到父元素节点
var ulObj = document.querySelector("ul");
// 获取ul节点下面所有的子节点li
for (var i = 0; i < ulObj.childNodes.length; i++) {
if (ulObj.childNodes[i].nodeType == 1) {
// 表示的是元素节点
console.log(ulObj.childNodes[i]);
}
}
</script>
</body>

5.3.2.2、方式二

1
2
3
4
5
# 方式
parentNode.children(非标准)
# 说明
1. parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回。
2. 虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>

</ul>
<script>
// 得到父元素节点
var ulObj = document.querySelector("ul");
// 获取ul节点下面所有的子节点li
console.log(ulObj.children);
</script>
</body>

5.3.3、获取第一个和最后一个子节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
// 得到父元素节点
var olObj = document.querySelector("ol");
// 获取ol节点的第一个子节点
console.log(olObj.firstChild); // #text
// 获取ol节点的最后一个子节点
console.log(olObj.lastChild); // #text

/*
说明
firstChild、lastChild 第一个子节点、最后一个节点 不管是文本节点还是元素节点
*/
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
// 得到父元素节点
var olObj = document.querySelector("ol");
// 获取ol节点的第一个元素子节点
console.log(olObj.firstElementChild); // <li>
// 获取ol节点的最后一个元素子节点
console.log(olObj.lastElementChild); // <li>

// 有兼容性问题,IE9+ 以上才支持。
</script>
</body>

​ 实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

解决方案:

  1. 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]

  2. 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
// 得到父元素节点
var olObj = document.querySelector("ol");
// 获取ol节点的第一个元素子节点
console.log(olObj.children[0]);
// 获取ol节点的最后一个元素子节点
console.log(olObj.children[olObj.children.length - 1]);
</script>
</body>

5.3.4、兄弟节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div>我是div1</div>
<div class="div2">我是div2</div>
<span>我是span</span>
<script>
var divObj = document.querySelector(".div2");

// 获取上一个兄弟节点
var preObj1 = divObj.previousSibling; // 包含文本节点
console.log(preObj1);
var preObj2 = divObj.previousElementSibling; // 兄弟元素节点
console.log(preObj2);

// 获取下一个兄弟节点
var nextObj1 = divObj.nextSibling;
console.log(nextObj1);

var nextObj2 = divObj.nextElementSibling;
console.log(nextObj2);
</script>
</body>

5.4、创建节点及添加节点

5.4.1、语法

1
2
3
4
5
6
7
8
9
10
# 1、创建节点
document.createElement('标签名')
创建由 标签名 指定的 HTML 元素,这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。

# 2、添加节点
a. node.appendChild(child)
该方法将一个节点添加到指定父节点的子节点列表末尾。

b. node.insertBefore(child, 指定元素)
该方法将一个节点添加到父节点的指定子节点前面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<ul>
<li>高圆圆</li>
</ul>
<script>
// 1、创建元素节点
var liObj = document.createElement("li");
liObj.innerHTML = '贾静雯';

// >> 添加li节点到ul节点的末尾
var ulObj = document.querySelector("ul");
ulObj.appendChild(liObj);

// 2、创建元素节点
var liObj2 = document.createElement("li");
liObj2.innerHTML = '赵敏';

// >> 添加li节点到ul节点中的高圆圆节点的前面
ulObj.insertBefore(liObj2, ulObj.children[0])
</script>
</body>

5.4.2、留言板案例

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
<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
// 1、获取元素
var textAreaObj = document.querySelector("textarea");
var btnObj = document.querySelector("button");
var ulObj = document.querySelector("ul");

// 2、绑定按钮事件
btnObj.onclick = function() {
// >> 获取内容
var content = textAreaObj.value;
if (content == null || content == '') {
alert("请输入内容");
return false;
}
// >> 创建li节点
var liObj = document.createElement("li");
liObj.innerHTML = content;

// >> 追加
ulObj.insertBefore(liObj, ulObj.children[0]);
}
</script>
</body>

5.5、删除节点

5.5.1、语法

1
2
# 语法
node.removeChild(child)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<button>删除</button>
<ul>
<li>高圆圆</li>
<li>贾静雯</li>
<li>赵敏</li>
</ul>
<script>
// 1、获取元素
var btnObj = document.querySelector("button");
var ulObj = document.querySelector("ul");

// 2、绑定按钮事件
btnObj.onclick = function() {
// 依次删除每一个li孩子
if (ulObj.children.length == 0) {
btnObj.disabled = true;
} else {
ulObj.removeChild(ulObj.children[0]);
}
}
</script>
</body>

5.5.2、留言板案例

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
<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
// 1、获取元素
var textAreaObj = document.querySelector("textarea");
var btnObj = document.querySelector("button");
var ulObj = document.querySelector("ul");

// 2、绑定按钮事件
btnObj.onclick = function() {
// >> 获取内容
var content = textAreaObj.value;
if (content == null || content == '') {
alert("请输入内容");
return false;
}
// >> 创建li节点
var liObj = document.createElement("li");
liObj.innerHTML = content;
// >> 创建a标签
var aObj = document.createElement("a");
aObj.innerHTML = '删除';
aObj.setAttribute("href", "javascript:void(0)");

// 绑定事件
aObj.onclick = function() {
this.parentNode.parentNode.removeChild(this.parentNode);
}

// >> 追加a节点
liObj.appendChild(aObj);

// >> 追加li节点
ulObj.insertBefore(liObj, ulObj.children[0]);
}
</script>
</body>

5.6、复制节点/克隆节点

5.6.1、语法

1
2
3
4
5
6
7
# 语法
node.cloneNode()
该方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点

# 注意点
1. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
2. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<ul>
<li>高圆圆</li>
<li>贾静雯</li>
<li>赵敏</li>
</ul>
<script>
// 1、获取元素
var ulObj = document.querySelector("ul");

// 2、>> node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
var liObj1 = ulObj.children[0].cloneNode();
ulObj.appendChild(liObj1);

// 3、>> node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
var liObj2 = ulObj.children[0].cloneNode(true);
ulObj.appendChild(liObj2);
</script>
</body>

5.6.2、动态生成表格

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
<body>
<table border="1px">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>

</tbody>
</table>
<script>
// 1.先去准备好学生的数据
var datas = [{
name: '贾静雯',
subject: 'JavaScript',
score: 100
}, {
name: '赵敏',
subject: 'HTML',
score: 98
}, {
name: '贾静雯',
subject: 'CSS',
score: 99
}];
// 2、获取tbody元素节点对象
var tbodyObj = document.querySelector("tbody");

// 3、数组中有多少个元素,就意味着有多少人,就意味着表格中有多少行
for (var i = 0; i < datas.length; i++) {
// >> 3.1 每循环一次就是创建一个tr
var trObj = document.createElement("tr");
// >> 3.2 有几个单元格,是取决于数组中的元素对象中有几个属性
for (var key in datas[i]) {
// >> 3.3 创建单元格
var tdObj = document.createElement("td");
// >> 3.4 向td单元格中添加内容
tdObj.innerHTML = datas[i][key];
// >> 3.5 将td追加到tr中
trObj.appendChild(tdObj);
}
// >> 3.6、创建由删除超链接的td
var delTdObj = document.createElement("td");
delTdObj.innerHTML = '<a href="javascript:;">删除 </a>';
trObj.appendChild(delTdObj);
// >> 3.7 追加到tbodyObj中
tbodyObj.appendChild(trObj);
}
// 超链接点击事件
var aObjs = document.querySelectorAll("a");
for (var i = 0; i < aObjs.length; i++) {
aObjs[i].onclick = function() {
// 此处不能使用aObjs[i].parentNode.parentNode , i 有作用域的问题
tbodyObj.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>