Javascript节点操作
节点操作是Javascript获取元素的方式之一。另一种是利用Javascript提供的DOM方法获取元素。常见的有getElementById,getElementsByTagName()等;
这种方法每获取一次元素就要getElement一次,较为繁琐(相对于节点操作而言)。我们可以使用节点操作,在获取某一个元素后,使用节点操作就可以直接获取它的子元素,子节点,兄弟节点等。
节点简介
节点在Javascript中包括文本节点,属性节点,元素节点,注释节点。节点具有节点类型(nodeType),节点值(nodeValue),节点名称(nodeName)。
节点类型 nodeType | 不同类型的节点具有不同的编号,如元素节点编号为1 |
节点名称 nodeName | 元素节点对应元素名,注释节点返回#comment,文本节点返回#text······ |
节点值 nodeValue | 仅限于文本,注释,XML的CDATA节点。其他节点的属性值为null,可读可写。 |
个人测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<style>
#box{
width: 100px;
height: 100px;
background-color: #ccc;
}
</style>
</head>
<body>
<div id="box" title="这是一个div" class="BB">
<!-- name -->
里面不是空的
<p>??</p>
</div>
<script>
var box=document.getElementById("box");
console.log(box.nodeName);//返回DIV
console.log(box.childNodes[1].nodeName);//返回#comment
console.log(box.childNodes[0].nodeName);//返回#text
console.log(box.nodeType);//元素节点nodeType是1
// console.log(box.attributes);//节点的所有属性节点作为一个数组保存在元素的attributes中
// 属性例如title="",class=""写在html标签内部
console.log(box.attributes[0].nodeType)//属性节点的nodeType为2
console.log(box.childNodes[0].nodeType);//文本节点的nodeType是3
console.log(box.childNodes[1].nodeType);//这里对应的是注释节点,nodeType对应8
//box.nodeValue=1222//为元素节点设置nodeValue会失败
//nodeValue属性只有文本节点,注释节点,XML的CDATA节点才具有,其他节点的nodeValue均为null
box.childNodes[1].nodeValue="name 已经过修改";
console.log(box.childNodes[1].nodeValue);//这里获取的是注释节点的nodeValue
</script>
</body>
</html>
nodeType各种节点对应值-以下图片摘自MDN 。个人感觉实际记忆价值不大,需要时能够查到即可。
节点操作实际属性和方法
属性
- Node.firstChild 返回当前节点的第一个子节点,没有就返回null。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(box.firstChild); </script> </body>
输出结果为取值为换行和空格的文本节点。
- Node.lastChild 返回当前节点的最后一个子节点,没有返回null。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(box.lastChild); </script> </body>
输出结果同样为值为换行和空格的文本节点。
-
以上两个方法由于可能获取到文本节点,常常使用firstElementNode lastElementNode这两个属性来获取第一个或最后一个元素节点。
<body> <ul id="uu"> <li>11</li> <li>22</li> <li>33</li> </ul> <script> var ul=document.getElementById("uu"); console.log(ul.firstElementChild); console.log(ul.lastElementChild); </script> </body>
输出结果就是第一个和最后一个li。
- Node.childNodes 返回一个具有当前节点的全部子节点的类数组,类数组没有push,pop等数组方法,但具有length属性。返回值是实时更新的,随着节点修改而改变。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(box.childNodes); </script> </body>
输出结果为类数组
-
Node.children 类似于childNodes,但是只是针对元素节点。
<body> <div id="box" title="这是一个div" class="BB"> <p>??</p> <span>11</span> </div> <script> var box=document.getElementById("box"); console.log(box.children); </script> </body>
以上为输出结果。
- Node.nodeValue 返回当前节点的节点值,可读可写。当对这个属性赋值时就可以修改属性值。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(pss.firstChild.nodeValue); </script> </body>
输出结果为??,也可以对这个属性进行修改,赋值字符串即可,此处不再展示。
- Node.nextSibling 返回当前节点的下一个兄弟节点。不可修改(可读不可写)
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(pss.nextSibling); </script> </body>
输出的是值为换行和空格的文本节点。
- Node.previousSibling 返回当前节点的上一个兄弟节点。可读不可写。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(pss.previousSibling); </script> </body>
输出内容
-
以上两个属性针对元素还有nextElementSibling,previousElementSibling。效果也是针对元素,避免获取文本节点,注释节点等其他节点。
<body> <ul id="uu"> <li>11</li> <li>22</li> <li>33</li> </ul> <script> var ul=document.getElementById("uu"); console.log(ul.children[1].nextElementSibling); console.log(ul.children[1].previousElementSibling); </script> </body>
输出结果分别是第三个节点,第一个节点。
- Node.parentNode 返回当前节点的父节点,没有则返回null。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(pss.parentNode); </script> </body>
输出内容为div元素。
- Node.parentElement 返回当前节点的父元素,没有则返回null。相对于上一个方法,更针对于获取元素,避免了父节点为非元素节点的可能。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(pss.parentNode); </script> </body>
输出内容也是div元素
- Node.textContent 返回当前节点的内部可视文本。不包括注释,display为none的元素内部文本,包括换行空格。(若想针对这个属性深入思考可以看本人的 另一篇博文)
输出内容<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; console.log(box.textContent); </script> </body>
方法
- Node.appendChild() 将参数指定的节点添加到当前节点的子节点,成为最后一个子节点。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); box.appendChild(ul); </script> </body>
修改后页面结构变为:
- Node.cloneNode() 参数是一个布尔值。为真,克隆内容包含当前节点的全部子代节点。为假时只是当前节点内容,不包括子代。这个方法会返回一个克隆节点,一般需要赋值到其他变量上来保存克隆出来的变量。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); var box_copy=box.cloneNode(true); console.log(box_copy); </script> </body>
输出的这个box_cpoy不在页面中,属于一个DOM外的节点。参数为真,复制的内容包括子节点及其内容。参数为假时复制不包括子节点。
- Node.contains() 参数是一个节点,作用是判定当前节点是否包含参数节点。包含则返回true,反之返回false。这里的包含关系可以是子代的子代······,仍会返回true。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); console.log(box.contains(pss)); </script> </body>
输出为true
- Node.hasChildNode() 无参数。作用是判定当前节点的子节点中是否含有子节点。返回值为布尔值。当然也可以使用node.firstNode!=null判断,node.childNodes.length!=0
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); console.log(ul.hasChildNodes()); </script> </body>
输出为false
- Node.insertBefore() 第一个参数是需要移动位置的节点,第二个参数是作为相对位置的节点,第一个参数节点会插入到第二个参数节点前。如果第一个参数节点已经出现在html文档中,这个方法就会移动该节点到新位置并删除原位置的节点。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); box.insertBefore(box.childNodes[3],box.childNodes[0]); </script> </body>
修改后网页结构
-
document.creatElement() 参数为一个表示标签名的字符串。返回值就是新创建的元素。这个方法创建元素后不会直接放到页面中,而是需要使用appendChild操作把元素放到页面中。
- Node.isEqualNode() 比较当前节点和参数节点是否是同一节点,比较范围包括属性和属性值,节点类型,节点值。相同返回true,反之返回false。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"></ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); console.log(box.childNodes[3].isEqualNode(pss)); </script> </body>
这里以两种方式访问同一节点,输出为true。
- Node.replaceChild() 第一个参数是新节点,第二个参数是被替换的节点。新节点如果已经出现在html文档中,原本位置的就会被删除。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"> </ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); ul.replaceChild(pss,ul.firstChild); </script> </body>
以上为修改后的网页结构。
- Node.removeNode() 参数是需要删除的子节点。该方法会返回被删除的节点。可以使用变量保存被删除节点(如果需要的话)。
<body> <div id="box" title="这是一个div" class="BB"> <!-- name --> 里面不 是空的 <p>??</p> </div> <ul id="ul"> </ul> <script> var box=document.getElementById("box"); var pss=document.getElementsByTagName("p")[0]; var ul=document.getElementById("ul"); ul.removeChild(ul.firstChild); </script> </body>
以上为修改后网页结构。删除了ul中的文本节点
- Node.normalize() 无参数,作用是规范化当前节点以及后代节点。会删去空文本节点,以及一些连续的文本节点。
<body> <div id="box" title="这是一个div" class="BB"></div> <script> var box=document.getElementById("box"); box.appendChild(document.createTextNode("1")); box.appendChild(document.createTextNode("2")); //初始化前 console.log(box.childNodes.length);//只有新增的两个节点 box.normalize(); //初始化后 console.log(box.childNodes.length);//只有一个节点 </script> </body>
- Node.getRootNode() 参数是一个布尔值。这个方法的作用返回是DOM树的根节点,即为HTMLDocument。参数默认为假,检索到shadow root就返回,为真则检索到普通root。(这玩意对笔者来说是没见过的新概念,有兴趣可以在 MDN上找到相关资料)
-
Node.compareDocumentPosition()(非重点)参数是另一个节点。作用是比较当前节点与另一节点的位置关系,返回值是一个十进制数值,不同数字代表不同含义。本人测试代码如下
console.log(box.compareDocumentPosition(box));//0 两者一致 console.log(box.compareDocumentPosition(box.previousSibling));//2 当前节点在另一个节点后面 console.log(box.compareDocumentPosition(box.nextSibling));//4 当前节点在另一个节点前面 console.log(box.compareDocumentPosition(box.parentNode));//10 当前节点是另一个节点的子节点 console.log(box.compareDocumentPosition(box.firstChild));//20 当前节点是另一个节点的父节点
这里值得一提的是本人查阅 MDN得到的结果与自行测试的结果不同,如有兴趣并懂得原因还请不吝赐教。
-
部分涉及命名空间的部分方法因笔者尚未进行命名空间的学习,不再展开赘述。以下逐一列出,大家可以自行参考学习。 Node.lookupNamespaceURI(), Node.lookupPrefix(), Node.isDefaultNamespace()
以上就是本次节点操作的相关知识点分享,本文参考MDN官方文档,这时并没有涉及废弃的方法。大家如由兴趣也可以在 这里查看MDN的相关资料。本文如有不足或错误之处,欢迎指正。
march on_6: 小马努力做时更博主
lucky_starr: 支持大佬
lucky_starr: 666大佬
lucky_starr:
lucky_starr: 马哥 牛