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 属性查看该对象的节点类型、节点名称、父节点和第一个子节点的名称。
- <div id="box">盒子</div>
- <script>
- var box = document.getElementById("box"); //获取指定盒子的引用
- var info = "nodeName:" + box.nodeName; //获取该节点的名称
- info += "\rnodeType:" + box.nodeType; //获取该节点的类型
- info += "\rparentNode:" + box.parentNode.nodeName; //获取该节点的父节点名称
- info += "\rchildNodes:" + box.childNodes[0].nodeName; //获取该节点的子节点的名称
- console.log(info); //显示提示信息
- </script>
2) getElementByTagName()方法
使用 getElementByTagName() 方法可以获取指定标签名称的所有元素。用法如下:
document.getElementsByTagName(tagName)
参数 tagName 表示指定名称的标签,该方法返回值为一个节点集合,使用 length 属性可以获取集合中包含元素的个数,利用下标可以访问其中某个元素对象。
【示例2】下面代码使用 for 循环获取每个 p 元素,并设置 p 元素的 class 属性为 red。
- var p = documeng.getElementsByTagName("p"); //获取p元素的所有引用
- for (var i = 0; i < p.length; i ++) { //遍历p数据集合
- p[i].setAttribute("class", "red"); //为每个p元素定义red类样式
- }
遍历元素
使用 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。
- var p = document.createElement("p"); //创建段落元素
- var info = "nodeName:" + p.nodeName; //获取元素名称
- info += ", nodeType:" + p.nodeType; //获取元素类型,如果为1则表示元素节点
- console.log(info);
使用 createElement() 方法创建的新元素不会被自动添加到文档里。如果要把这个元素添加到文档里,还需要使用 appendChild()、insertBefore() 或 replaceChild() 方法实现。
【示例2】下面代码演示如何把新创建的 p 元素增加到 body 元素下。当元素被添加到文档树中,就会立即显示出来。
- var p = document.createElement("p"); //创建段落元素
- document.body.appendChild(p); //增加段落元素到body元素下
复制节点
cloneNode() 方法可以创建一个节点的副本。
【示例1】在下面示例中,首先创建一个节点 p,然后复制该节点为 p1,再利用 nodeName 和 nodeType 属性获取复制节点的基本信息,该节点的信息与原来创建的节点基本相同。
- var p = document.createElement("p"); //创建节点
- var p1 = p.cloneNode(false); //复制节点
- var info = "nodeName:" + p1.nodeName; //获取复制节点的名称
- info += ", nodeType:" + p1.nodeType; //获取复制节点的类型
- console.log(info); //显示复制节点的名称和类型相同
【示例2】以示例 1 为基础,在创建一个文本节点之后,尝试把复制的文本节点增加到段落元素之中,再把段落元素增加到标题元素中,最后把标题元素增加到 body 元素中。如果此时调用复制文本节点的 nodeName 和 nodeType 属性,则返回的 nodeType 属性值为 3,而 nodeName 属性值为 #text。
- var p = document.createElement("p"); //创建一个p元素
- var h1 = document.createElement("h1"); //创建一个h1元素
- var txt = document.createTextNode("Hello World"); //创建一个文本节点
- var hello = txt.cloneNode(false); //复制创建的文本节点
- p.appendChild(txt); //把复制的文本节点增加到段落节点中
- h1.appendChid(p); //把段落节点增加到标题节点中
- document.body.appendChild(h1); //把标题节点增加到body节点中
【示例3】下面示例演示了如何复制一个节点及所有包含的子节点。当复制其中创建的标题 1 节点之后,该节点所包含的子节点及文本节点豆浆杯复制过来,然后增加到 body 元素的尾部。
- var p = document.createElement("p"); //创建一个p元素
- var h1 = document.createElement("h1"); //创建一个h1元素
- var txt = document.createTextNode("Hello World"); //创建一个文本节点
- p.appendChild(txt); //把复制的文本节点增加到段落节点中
- h1.appendChid(p); //把段落节点增加到标题节点中
- document.body.appendChild(h1); //把标题节点增加到body节点中
- var new_h1 = h1.cloneNode(true); //复制标题元素及其所有子节点
- document.body.appendChild(new_h1); //把复制的新标题元素增加到文档中
由于复制的节点会包含原节点的所有特性,如果节点中包含 id 属性,就会出现 id 属性值重叠的情况。一般情况下,在同一个文档中,不同属性的 id 属性值应该不同。为了避免潜在冲突,应修改其中某个节点的 id 属性值。
插入节点
在文档中插入节点主要包括两种方法:
1) appendChild()方法
appendChild() 方法可向当前节点的子节点列表的末尾添加新的子节点。用法如下:
appendChild(newchild)
参数 newchild 表示新添加的节点对象,并返回新增的节点。
【示例1】下面示例展示了如何把段落文本增加到文档中的指定的 div 元素中,使它成为当前节点的最后一个子节点。
- <div id="box"></div>
- <script>
- var p = document.createElement("p"); //创建段落节点
- var txt = document.createTextNode("盒模型"); //创建文本节点,文本内容为“盒模型”
- p.appendChild(txt); //把文本节点增加到段落节点中
- document.getElementById("box").appendChild(p); //获取box元素,把段落节点增加尽量
- </script>
如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置。如果添加的节点是 DocumentFragment 节点,则不会直接插入,而是把它的子节点插入当前节点的末尾。
将元素添加到文档树中,浏览器会立即呈现该元素。此后,对这个元素所作的任何修改都会实时反映在浏览器中。
【示例2】在下面示例中,新建两个盒子和一个按钮,使用 CSS 设计两个盒子显示为不同的效果;然后为按钮绑定事件处理程序,设计当点击按钮时执行插入操作。
- <div id="red">
- <h1>红盒子</h1>
- </div>
- <div id="blue">蓝盒子</div>
- <button id="ok">移动</button>
- <script>
- var ok = document.getElementById("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件的处理函数
- var red = document.getElementById("red"); //获取红色盒子的引用
- var blue= document.getElementById("blue"); //获取蓝色盒子的引用
- blue.appendChild(red); //最后移动红色盒子到蓝色盒子中
- }
- </script>
上面代码使用 appendChild() 方法把红盒子移动到蓝色盒子中间。在移动指定节点时,会同时移动指定节点包含的所有子节点,演示效果如图所示。
2) insertBefore()方法
使用 insertBefore() 方法可在已有的子节点前插入一个新的子节点。用法如下:
insertBefore(newchild, refchild)
其中参数 newchild 表示新插入的节点,refchild 表示插入新节点的节点,用于指定插入节点的后面相邻位置。插入成功后,该方法将返回新插入的子节点。
【示例3】针对示例 2 ,如果把蓝盒子移动到红盒子所包含的标题元素的前面,使用 appendChild() 方法是无法实现的,此时可以使用 insertBefore() 方法来实现。
- var ok = documeng.getElementById("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var red = document.getElementById("red"); //获取红色盒子的引用
- var blue = document.getElementById("blue"); //获取蓝色盒子的引用
- var h1 = document.getElementsByTagName("h1")[0]; //获取标题元素的引用
- red.insertBefore(blue, h1); //把蓝色盒子移动到红色盒子内,且位于标题前面
- }
当单击“移动”按钮之后,蓝色盒子被移动到红色盒子内部,且位于标题元素前面。演示效果如下:
insertBefore() 方法与 appendChild() 方法一样,可以把指定元素及其所包含的所有子节点都一起插入到指定位置中。同时会先删除移动的元素,再重新插入到新的位置。
删除节点
removeChild() 方法可以从子节点列表中删除某个节点。用法如下:
nodeObject.removeChild(node)
其中参数 node 为要删除节点。如果删除成功,则返回被删除节点;如果失败,则返回 null。
当使用 removeChild() 方法删除节点时,该节点所包含的所有子节点将同时被删除。
【示例1】在下面的示例中单击按钮时将删除红盒子中的一级标题。
- <div id="red">
- <h1>红盒子</h1>
- </div>
- <div id="blue">蓝盒子</div>
- <button id="ok">移动</button>
- <script>
- var ok = document.getElementById ("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var red = document.getElementById ("red"); //获取红色盒子的引用
- var h1 = document.getElementsByTagName("h1")[0]; //获取标题元素的引用
- red.removeChild(h1); //移出红盒子包含的标题元素
- }
- </script>
【示例2】如果想删除蓝色盒子,但是又无法确定它的父元素,此时可以使用 parentNode 属性来快速获取父元素的引用,并借助这个引用来实现删除操作。
- var ok = document.getElementById ("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var blue= document.getElementById ("blue"); //获取蓝色盒子的引用
- var parent = blue.parentNode; //获取蓝色盒子父元素的引用
- parent.removeChild(blue); //移出蓝色盒子
- }
如果希望把删除节点插入到文档其他位置,可以使用 removeChild() 方法,也可以使用 appendChild() 和 insertBefore() 方法来实现。
【示例3】在 DOM 文档操作中删除节点与创建和插入节点一样都是使用最频繁的,为此可以封装删除节点操作函数。
- //封装删除节点函数
- //参数:e表示预删除的节点
- //返回值:返回被删除的节点,如果不存在指定的节点,则返回undefined值
- function remove (e) {
- if (e) {
- var _e = e.parentNode.removeChild(e);
- return _e;
- }
- return undefined;
- }
【示例4】如果要删除指定节点下的所有子节点,则封装的方法如下:
- //封装删除所有子节点的方法
- //参数:e表示预删除所有子节点的父节点
- function empty (e) {
- while (e.firstChild) {
- e.removeChild (e.firstChild);
- }
- }
替换节点
replaceChild() 方法可以将某个子节点替换为另一个。用法如下:
nodeObject.replaceChild(new_node, old_node)
其中参数 new_node 为指定新的节点,old_node 为被替换的节点。如果替换成功,则返回被替换的节点;如果替换失败,则返回 null。
【示例1】以上示例为基础重写脚本,新建一个二级标题元素并替换掉红色盒子中的一级标题元素。
- var ok = document.getElementById("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var red = document.getElementById("red"); //获取红色盒子的引用
- var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
- var h2 = documeng.createElement("h2"); //创建二级标题元素并引用
- red.replaceChild(h2, h1); //把一级标题替换为二级标题
- }
演示发现,当使用新创建的二级标题替换一级标题之后,原来的一级标题所包含的标题文本已经不存在了。这说明替换节点的操作不是替换元素名称,而是替换其包含的所有子节点以及其包含的所有内容。
同样的道理,如果替换节点还包含子节点,则子节点将一同被插入到被替换的节点中。可以借助 replaceChild() 方法在文档中使用现有的节点替换另一个存在的节点。
【示例2】在下面示例中使用蓝盒子替换掉红盒子中包含的一级标题元素。此时可以看到,蓝盒子原来显示的位置已经被删除显示,同时被替换元素 h1 也被删除。
- var ok = document.getElementById("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var red = document.getElementById("red"); //获取红色盒子的引用
- var blue= document.getElementById("blue"); //获取蓝色盒子的引用
- var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
- red.replaceChild(blue, h1); //把红盒子中包含的一级标题替换为蓝盒子
- }
【示例3】replaceChild() 方法能够返回被替换掉的节点引用,因此还可以把被替换掉的元素给找回来,并增加到文档中的指定节点中。针对上面示例,使用一个变量 del_h1 存储被替换掉的一级标题,然后再把它插入到红色盒子前面。
- var ok = document.getElementById("ok"); //获取按钮元素的引用
- ok.onclick = function () { //为按钮注册一个鼠标单击事件处理函数
- var red = document.getElementById("red"); //获取红色盒子的引用
- var blue= document.getElementById("blue"); //获取蓝色盒子的引用
- var h1 = document.getElementsByTagName("h1")[0]; //获取一级标题的引用
- var del_h1 = red,replaceChild(blue, h1); //把红盒子中包含的一级标题替换为蓝盒子
- red.parentNode.insertBefore(del_h1, red); //把替换掉的一级标题插入到红盒子前面
- }