JS操作元素节点(非常详细)

在客户端开发中,大部分操作都是针对元素节点的。主要特征值:nodeType 等于 1,nodeName 等于标签名称,nodeValue 等于 null。元素节点包括 5 个公共属性:id(标识符)、title(提示标签)、lang(语言编码)、dir(语言方向)、className(CSS 类样式),这些属性可读可写。

访问元素

1) getElementById()方法

使用 getElementById() 方法可以准确获取文档中指定元素。用法如下:

document.getElementById(ID);

参数 ID 表示文档中对应元素的 id 属性值。如果文档中不存在指定元素,则返回值为 null。该方法只适用于 document 对象。

【示例1】在下面示例中,使用 getElementById() 方法获取 <div id="box"> 对象,然后使用 nodeName、nodeType、parentNode 和 childNodes 属性查看该对象的节点类型、节点名称、父节点和第一个子节点的名称。

  1. <div id="box">盒子</div>
  2. <script>
  3. var box = document.getElementById("box"); //获取指定盒子的引用
  4. var info = "nodeName:" + box.nodeName; //获取该节点的名称
  5. info += "\rnodeType:" + box.nodeType; //获取该节点的类型
  6. info += "\rparentNode:" + box.parentNode.nodeName; //获取该节点的父节点名称
  7. info += "\rchildNodes:" + box.childNodes[0].nodeName; //获取该节点的子节点的名称
  8. console.log(info); //显示提示信息
  9. </script>

2) getElementByTagName()方法

使用 getElementByTagName() 方法可以获取指定标签名称的所有元素。用法如下:

document.getElementsByTagName(tagName)

参数 tagName 表示指定名称的标签,该方法返回值为一个节点集合,使用 length 属性可以获取集合中包含元素的个数,利用下标可以访问其中某个元素对象。

【示例2】下面代码使用 for 循环获取每个 p 元素,并设置 p 元素的 class 属性为 red。

  1. var p = documeng.getElementsByTagName("p"); //获取p元素的所有引用
  2. for (var i = 0; i < p.length; i ++) { //遍历p数据集合
  3. p[i].setAttribute("class", "red"); //为每个p元素定义red类样式
  4. }

遍历元素

使用 parentNode、nextSibling、previousSibling、firstChild 和 lastChild 属性可以遍历文档树中任意类型节点,包括空字符(文本节点)。HTML 5 新添加 5 个属性专门访问元素节点。

  • childElementCount:返回子元素的个数,不包括文本节点和注释。
  • firstElementChild:返回第一个子元素。
  • lastElementChild:返回最后一个子元素。
  • previousElementSibling:返回前一个相邻兄弟元素。
  • nextElementSibling:返回后一个相邻兄弟元素。


浏览器支持:IE9+、FireFox3.5+、Safari4+、Chrome 和 Opera10+。

创建元素

使用 document 对象的 createElement() 方法能够根据参数指定的标签名称创建一个新的元素,并返回新建元素的引用。用法如下:

var element = document.getElement("tagName");

其中,element 表示新建元素的引用,createElement() 是 document 对象的一个方法,该方法只有一个参数,用来指定创建元素的标签名称。

【示例1】下面代码在当前文档中创建了一个段落标记 p,存储到变量 p 中。由于该变量表示一个元素节点,所以它的 nodeType 属性值等于 1,而 nodeName 属性值等于 p。

  1. var p = document.createElement("p"); //创建段落元素
  2. var info = "nodeName:" + p.nodeName; //获取元素名称
  3. info += ", nodeType:" + p.nodeType; //获取元素类型,如果为1则表示元素节点
  4. console.log(info);

使用 createElement() 方法创建的新元素不会被自动添加到文档里。如果要把这个元素添加到文档里,还需要使用 appendChild()、insertBefore() 或 replaceChild() 方法实现。

【示例2】下面代码演示如何把新创建的 p 元素增加到 body 元素下。当元素被添加到文档树中,就会立即显示出来。

  1. var p = document.createElement("p"); //创建段落元素
  2. document.body.appendChild(p); //增加段落元素到body元素下

复制节点

cloneNode() 方法可以创建一个节点的副本。

【示例1】在下面示例中,首先创建一个节点 p,然后复制该节点为 p1,再利用 nodeName 和 nodeType 属性获取复制节点的基本信息,该节点的信息与原来创建的节点基本相同。

  1. var p = document.createElement("p"); //创建节点
  2. var p1 = p.cloneNode(false); //复制节点
  3. var info = "nodeName:" + p1.nodeName; //获取复制节点的名称
  4. info += ", nodeType:" + p1.nodeType; //获取复制节点的类型
  5. console.log(info); //显示复制节点的名称和类型相同


【示例2】以示例 1 为基础,在创建一个文本节点之后,尝试把复制的文本节点增加到段落元素之中,再把段落元素增加到标题元素中,最后把标题元素增加到 body 元素中。如果此时调用复制文本节点的 nodeName 和 nodeType 属性,则返回的 nodeType 属性值为 3,而 nodeName 属性值为 #text。

  1. var p = document.createElement("p"); //创建一个p元素
  2. var h1 = document.createElement("h1"); //创建一个h1元素
  3. var txt = document.createTextNode("Hello World"); //创建一个文本节点
  4. var hello = txt.cloneNode(false); //复制创建的文本节点
  5. p.appendChild(txt); //把复制的文本节点增加到段落节点中
  6. h1.appendChid(p); //把段落节点增加到标题节点中
  7. document.body.appendChild(h1); //把标题节点增加到body节点中


【示例3】下面示例演示了如何复制一个节点及所有包含的子节点。当复制其中创建的标题 1 节点之后,该节点所包含的子节点及文本节点豆浆杯复制过来,然后增加到 body 元素的尾部。

  1. var p = document.createElement("p"); //创建一个p元素
  2. var h1 = document.createElement("h1"); //创建一个h1元素
  3. var txt = document.createTextNode("Hello World"); //创建一个文本节点
  4. p.appendChild(txt); //把复制的文本节点增加到段落节点中
  5. h1.appendChid(p); //把段落节点增加到标题节点中
  6. document.body.appendChild(h1); //把标题节点增加到body节点中
  7. var new_h1 = h1.cloneNode(true); //复制标题元素及其所有子节点
  8. document.body.appendChild(new_h1); //把复制的新标题元素增加到文档中


由于复制的节点会包含原节点的所有特性,如果节点中包含 id 属性,就会出现 id 属性值重叠的情况。一般情况下,在同一个文档中,不同属性的 id 属性值应该不同。为了避免潜在冲突,应修改其中某个节点的 id 属性值。

插入节点

在文档中插入节点主要包括两种方法:

1) appendChild()方法

appendChild() 方法可向当前节点的子节点列表的末尾添加新的子节点。用法如下:

appendChild(newchild)

参数 newchild 表示新添加的节点对象,并返回新增的节点。

【示例1】下面示例展示了如何把段落文本增加到文档中的指定的 div 元素中,使它成为当前节点的最后一个子节点。

  1. <div id="box"></div>
  2. <script>
  3. var p = document.createElement("p"); //创建段落节点
  4. var txt = document.createTextNode("盒模型"); //创建文本节点,文本内容为“盒模型”
  5. p.appendChild(txt); //把文本节点增加到段落节点中
  6. document.getElementById("box").appendChild(p); //获取box元素,把段落节点增加尽量
  7. </script>

如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置。如果添加的节点是 DocumentFragment 节点,则不会直接插入,而是把它的子节点插入当前节点的末尾。

将元素添加到文档树中,浏览器会立即呈现该元素。此后,对这个元素所作的任何修改都会实时反映在浏览器中。

【示例2】在下面示例中,新建两个盒子和一个按钮,使用 CSS 设计两个盒子显示为不同的效果;然后为按钮绑定事件处理程序,设计当点击按钮时执行插入操作。

  1. <div id="red">
  2. <h1>红盒子</h1>
  3. </div>
  4. <div id="blue">蓝盒子</div>
  5. <button id="ok">移动</button>
  6. <script>
  7. var ok = document.getElementById("ok"); //获取按钮元素的引用
  8. ok.onclick = function () { //为按钮注册一个鼠标单击事件的处理函数
  9. var red = document.getElementById("red"); //获取红色盒子的引用
  10. var blue= document.getElementById("blue"); //获取蓝色盒子的引用
  11. blue.appendChild(red); //最后移动红色盒子到蓝色盒子中
  12. }
  13. </script>

上面代码使用 appendChild() 方法把红盒子移动到蓝色盒子中间。在移动指定节点时,会同时移动指定节点包含的所有子节点,演示效果如图所示。

JS操作元素节点(非常详细)
  JS操作元素节点(非常详细)

2) insertBefore()方法

使用 insertBefore() 方法可在已有的子节点前插入一个新的子节点。用法如下:

insertBefore(newchild, refchild)

其中参数 newchild 表示新插入的节点,refchild 表示插入新节点的节点,用于指定插入节点的后面相邻位置。插入成功后,该方法将返回新插入的子节点。

【示例3】针对示例 2 ,如果把蓝盒子移动到红盒子所包含的标题元素的前面,使用 appendChild() 方法是无法实现的,此时可以使用 insertBefore() 方法来实现。

  1. var ok = documeng.getElementById("ok"); //获取按钮元素的引用
  2. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  3. var red = document.getElementById("red"); //获取红色盒子的引用
  4. var blue = document.getElementById("blue"); //获取蓝色盒子的引用
  5. var h1 = document.getElementsByTagName("h1")[0]; //获取标题元素的引用
  6. red.insertBefore(blue, h1); //把蓝色盒子移动到红色盒子内,且位于标题前面
  7. }

当单击“移动”按钮之后,蓝色盒子被移动到红色盒子内部,且位于标题元素前面。演示效果如下:

JS操作元素节点(非常详细)
  JS操作元素节点(非常详细)


insertBefore() 方法与 appendChild() 方法一样,可以把指定元素及其所包含的所有子节点都一起插入到指定位置中。同时会先删除移动的元素,再重新插入到新的位置。

删除节点

removeChild() 方法可以从子节点列表中删除某个节点。用法如下:

nodeObject.removeChild(node)

其中参数 node 为要删除节点。如果删除成功,则返回被删除节点;如果失败,则返回 null。

当使用 removeChild() 方法删除节点时,该节点所包含的所有子节点将同时被删除。

【示例1】在下面的示例中单击按钮时将删除红盒子中的一级标题。

  1. <div id="red">
  2. <h1>红盒子</h1>
  3. </div>
  4. <div id="blue">蓝盒子</div>
  5. <button id="ok">移动</button>
  6. <script>
  7. var ok = document.getElementById ("ok"); //获取按钮元素的引用
  8. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  9. var red = document.getElementById ("red"); //获取红色盒子的引用
  10. var h1 = document.getElementsByTagName("h1")[0]; //获取标题元素的引用
  11. red.removeChild(h1); //移出红盒子包含的标题元素
  12. }
  13. </script>


【示例2】如果想删除蓝色盒子,但是又无法确定它的父元素,此时可以使用 parentNode 属性来快速获取父元素的引用,并借助这个引用来实现删除操作。

  1. var ok = document.getElementById ("ok"); //获取按钮元素的引用
  2. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  3. var blue= document.getElementById ("blue"); //获取蓝色盒子的引用
  4. var parent = blue.parentNode; //获取蓝色盒子父元素的引用
  5. parent.removeChild(blue); //移出蓝色盒子
  6. }

如果希望把删除节点插入到文档其他位置,可以使用 removeChild() 方法,也可以使用 appendChild() 和 insertBefore() 方法来实现。

【示例3】在 DOM 文档操作中删除节点与创建和插入节点一样都是使用最频繁的,为此可以封装删除节点操作函数。

  1. //封装删除节点函数
  2. //参数:e表示预删除的节点
  3. //返回值:返回被删除的节点,如果不存在指定的节点,则返回undefined值
  4. function remove (e) {
  5. if (e) {
  6. var _e = e.parentNode.removeChild(e);
  7. return _e;
  8. }
  9. return undefined;
  10. }


【示例4】如果要删除指定节点下的所有子节点,则封装的方法如下:

  1. //封装删除所有子节点的方法
  2. //参数:e表示预删除所有子节点的父节点
  3. function empty (e) {
  4. while (e.firstChild) {
  5. e.removeChild (e.firstChild);
  6. }
  7. }

替换节点

replaceChild() 方法可以将某个子节点替换为另一个。用法如下:

nodeObject.replaceChild(new_node, old_node)

其中参数 new_node 为指定新的节点,old_node 为被替换的节点。如果替换成功,则返回被替换的节点;如果替换失败,则返回 null。

【示例1】以上示例为基础重写脚本,新建一个二级标题元素并替换掉红色盒子中的一级标题元素。

  1. var ok = document.getElementById("ok"); //获取按钮元素的引用
  2. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  3. var red = document.getElementById("red"); //获取红色盒子的引用
  4. var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
  5. var h2 = documeng.createElement("h2"); //创建二级标题元素并引用
  6. red.replaceChild(h2, h1); //把一级标题替换为二级标题
  7. }

演示发现,当使用新创建的二级标题替换一级标题之后,原来的一级标题所包含的标题文本已经不存在了。这说明替换节点的操作不是替换元素名称,而是替换其包含的所有子节点以及其包含的所有内容。

同样的道理,如果替换节点还包含子节点,则子节点将一同被插入到被替换的节点中。可以借助 replaceChild() 方法在文档中使用现有的节点替换另一个存在的节点。

【示例2】在下面示例中使用蓝盒子替换掉红盒子中包含的一级标题元素。此时可以看到,蓝盒子原来显示的位置已经被删除显示,同时被替换元素 h1 也被删除。

  1. var ok = document.getElementById("ok"); //获取按钮元素的引用
  2. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  3. var red = document.getElementById("red"); //获取红色盒子的引用
  4. var blue= document.getElementById("blue"); //获取蓝色盒子的引用
  5. var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
  6. red.replaceChild(blue, h1); //把红盒子中包含的一级标题替换为蓝盒子
  7. }


【示例3】replaceChild() 方法能够返回被替换掉的节点引用,因此还可以把被替换掉的元素给找回来,并增加到文档中的指定节点中。针对上面示例,使用一个变量 del_h1 存储被替换掉的一级标题,然后再把它插入到红色盒子前面。

  1. var ok = document.getElementById("ok"); //获取按钮元素的引用
  2. ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
  3. var red = document.getElementById("red"); //获取红色盒子的引用
  4. var blue= document.getElementById("blue"); //获取蓝色盒子的引用
  5. var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
  6. var del_h1 = red,replaceChild(blue, h1); //把红盒子中包含的一级标题替换为蓝盒子
  7. red.parentNode.insertBefore(del_h1, red); //把替换掉的一级标题插入到红盒子前面
  8. }
上一篇:CSS - CSS 选择器


下一篇:使用JavaScript中的setInterval()实现当前时间动态显示