最近虽然一直在做一些小任务,但是发现对HTML元素的操作并不十分清楚,完全是为了实现而实现,代码质量太低,于是准备将DOM梳理一下。

HTML DOM节点树

简单讲,通过HTML DOM,树中的所有节点都可以通过JavaScript的代码进行访问,即对HTML的元素进行修改、添加、删除等操作。此本分务必熟练掌握。

为了便于理解关于节点问题,我从W3c引一个例子,如下代码段:

1
2
3
4
5
6
7
8
9
<html>
<head>
<title>DOM 教程</title>
</head>
<body>
<h1>DOM 第一课</h1>
<p>Hello world!</p>
</body>
</html>

从上面代码中

  • <head> 和 <body> 的父节点是 <html> 节点
  • 文本节点 “Hello world!” 的父节点是 <p> 节点
  • <title> 节点也拥有一个子节点:文本节点 “DOM 教程”
  • <h1> 和 <p> 节点是同胞节点,同时也是 <body> 的子节点
    并且:
  • <head> 元素是 <html> 元素的首个子节点
  • <body> 元素是 <html> 元素的最后一个子节点

(顺便说一句,由于Markdown语法是最终变成HTML代码,所以尖括号会无法显示,于是可用’&lt加一个;’代替前尖括号,用’&gt加一个;’代替后尖括号。)

HTML DOM常用方法及对象

一些常用的 HTML DOM 方法:

  • getElementById(id) - 获取带有指定 id 的节点(元素)
  • appendChild(node) - 插入新的子节点(元素)
  • removeChild(node) - 删除子节点(元素)

一些常用的 HTML DOM 属性:

  • innerHTML - 节点(元素)的文本值
  • parentNode - 节点(元素)的父节点
  • childNodes - 节点(元素)的子节点
  • attributes - 节点(元素)的属性节点

以上内容基本为概念,下面开始测试。

一、元素内容的获取

本块测试将测试innerHTML、nodeValue属性对元素内容的获取,以及nodeName及nodeType的作用测试。

将要操作的HTML代码如下:

1
2
3
4
<div id="div">
<h1 id="h1">Hello</h1>
<p id="p">Word</p>
</div>

1、innerHTML获取目标内容:

1
2
var text1 = document.getElementById('h1').innerHTML;
document.write(text1);

可以看到innerHTML直接获取了目标内容,虽然此时处在文本节点的父节点位置。

2、nodeValue获取:

1
2
var text2 = document.getElementById('h1');
document.write(text2.firstChild.nodeValue);

需要注意的是当获取id之后此时处于h1元素位置处,innerHTML可以直接获取内容。而nodeValue则需先用firstChild等获取目标文本节点,然后用nodeValue获取内容。

** 补充nodeName作用 **
nodeName 属性规定节点的名称。

  • 元素节点的 nodeName 与标签名相同
  • 属性节点的 nodeName 与属性名相同
  • 文本节点的 nodeName 始终是 #text

** 补充nodeType作用 **
nodeType 属性返回节点的类型。nodeType 是只读的。

二、元素的访问

访问这部分主要测试getElementsByTagName() 方法、getElementsByClassName() 方法这两个。

将要操作的HTML代码如下:

1
2
3
4
5
6
7
<p id="p1" class="x">这句为div外面第一个p</p>
<p >这句为div外面第二个p</p>
<div id="div" class="x">
<h1 id="h1" class="x">Hello</h1>
<p id="p2" class="x">这句为div里面第一个p</p>
<p id="p3">这句为div里面第二个p</p>
</div>

1、getElementsByTagName方法

作用:getElementsByTagName() 返回带有指定标签名的所有元素。

1
2
3
4
var t1 = document.getElementsByTagName('p');
document.write(t1[0].innerHTML);
document.write(t1[2].innerHTML);
document.write('<br>');

上例输出为:
这句为div外面第一个p这句为div里面第一个p

1
2
3
4
//当已经用getElementById获取时
var t2 = document.getElementById('div').getElementsByTagName('p');
document.write(t2[0].innerHTML);
document.write('<br>');

输出为:
这句为div里面第一个p

从上面两例可以看出当没有限定时,获取到的元素为所有部分,但是当已经限定在id为div的标签时,此时则只会获取到标签内的部分。

2、getElementsByClassName方法

如果希望查找带有相同类名的所有 HTML 元素,请使用这个方法。
注意该方法与IE 5,6,7,8不兼容

1
2
3
4
5
var t3 = document.getElementsByClassName('x');
document.write(t3[0].innerHTML);

//当获取到整块div时,innerHTML会将整个内容获取
document.write(t3[1].innerHTML);

注意浏览器的兼容性,尽量少用该方法,或直接用相应代码兼容IE低版本。

三、元素的修改

这部分内容并不复杂,因此把代码贴上,以便查看即可。

1
2
3
4
5
6
<p id="p1">Hello</p>
<script type="text/javascript">
//元素修改
document.getElementById('p1').innerHTML = "World";
document.getElementById('p1').style.color = 'blue';
</script>

上面的操作即修改内容,以及修改CSS样式。

四、元素的添加与删除

元素内容的添加与删除是DOM操作的核心,这部分较为重要,综合运用了以上三部分内容。

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
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p id="p1">Hello</p>
<div id="a">
<p id="p2">第一行</p>
<p id="p3">第二行</p>
</div>
<script type="text/javascript">
//元素修改
document.getElementById('p1').innerHTML = "World";
document.getElementById('p1').style.color = 'blue';

//appendChild插入
var node = document.createElement('p');
var textNode = document.createTextNode("第三行");
node.appendChild(textNode);
var element = document.getElementById('a');
element.appendChild(node);

//使用insertBefore
var new_node = document.createElement('p');
var new_textNode = document.createTextNode('第零行');
new_node.appendChild(new_textNode);
var child1 = document.getElementById('p2');
element.insertBefore(new_node,child1);

//removeChild删除
var child2 = document.getElementById('p2');
element.removeChild(child2);

//使用parentNode查找其父元素
var child3 = document.getElementById('p3');
child3.parentNode.removeChild(child3);
</script>
</body>
</html>
  • appendChild() 作为父元素最后一个子元素插入
  • insertBefore() 插入想要插入元素之前
  • removeChild() 删除相应元素(需先获取其父元素)
  • parentNode() 查找其父元素(可应用于上一方法)

说到查找元素,这里还要比较一下childNodes和children的区别,两者都是获取父元素的子元素,但是具体实现功能还是不太一样。测试如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<p id="p1">Hello world!</p>
<div id="parent">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>

<script>
var p = document.getElementById('parent');
document.write(p.childNodes[0].nodeName+"<br>");
document.write(p.children[0].nodeName);
p.childNodes[3].innerHTML = "新行";
</script>

输出结果为

可以看到childNodes[0]所指向的元素是div中的文本节点,而children[0]则指向的是div中的第一个p节点,因此可以看出childNodes更加的细致,而children更加的好用,而且便于理解。

五、对事件作出反应

本部分简要提一下主要内容

  • onclick 用户点击完成时触发
  • onload 用户进入页面时触发
  • onchange 当用户改变输入字段时触发(一般用于input标签)
  • onmouseover 鼠标指针移动到元素时触发
  • onmouseout 鼠标指针离开元素时触发
  • onmousedown 鼠标按钮点击时触发
  • onmouseup 鼠标按钮被松开时触发

总结

DOM操作基本内容大概就这么多,虽然整理了这么多,对这些也有了一个更加清晰的认识,但是离熟练使用还有一段距离,还是要不断的多练习,才能有更大的提高。继续努力。