首页 > JavaScript 阅读:284

JS DOM常用节点

 
DOM 节点的类型实际上有 12 种,但其中绝大部分的节点不是在 HTML 文档中不太常用,就是因在各大浏览器中的行为尚不一致而不被推荐,所以我们实际只需要熟悉平时常用到的节点类型只有:文档节点、元素节点、属性节点、文本节点以及注释节点。下面就逐一介绍这些节点类型以及它们所提供的接口。

文档节点:

文档节点通常用于代表整个 XML 或 HTML 文档,换句话说,一个文档的 DOM 树结构中往往有且只能有一个文档节点。
文档节点的 nodeType 的值为 9、nodeName 的值为 #document、nodeValue 的值为 null。而在浏览器环境下,文档节点事实上是一个名为 document 的全局对象,我们通常通过这个对象来获取当前 HTML 页面中的信息,并对页面中的元素执行各种操作。下面介绍 DOM 标准为文档节点定义的专用接口:
  • documentElement 属性:在 HTML 文档中,这个属性代表的是当前页面的 <html> 标签,它在 DOM 树结构中对应着一个元素类型的节点。在某些浏览器的实现中,该节点有时也是文档节点的第一个子节点。对此,我们可以用下面的代码来验证一下:
         const htmlNode = document.documentElement;
         console.log(htmlNode == document.firstChild);
         // 某些浏览器会输出false,而另一些则输出 true
  • body 属性:在 HTML 文档中,这个属性代表的是当前页面的 <body> 标签,它在 DOM 树结构中对应着一个元素类型的节点。由于在 Web 开发中我们要执行的绝大部分操作针对的都是该节点的子节点,所以该属性应该是 document 对象使用频率最高的属性之一了。与此同时,它在通常情况下还应该是 htmlNode 节点的最后一个子节点,我们可以接着上面的代码继续来验证一下:
         const bodyNode = document.body;
         console.log(bodyNode == htmlNode.lastChild);
  • title 属性:该属性中存储的是 <title> 标签中的文本,该文本通常会出现在浏览器窗口的标题栏和标签页中。我们可以用该属性来修改当前页面的标题,例如:        
         console.log(document.title); // 输出现有标题
         document.title = 'new title';
         console.log(document.title); // 输出:new title
  • URL 属性:该属性中存储的是当前页面在浏览器地址栏中显示的 URL,我们是通过该 URL 来向服务器发送访问当前页面的请求的。
  • domain 属性:该属性中存储的是当前页面的 URL 所属的域名。例如,假设当前页面的 URL 是 http://owlman.org/index.htm,该属性值就是 owlman.org。
  • referrer 属性:该属性中存储的是链接到当前页面的那个页面的 URL。例如,假设我们是通过 http://owlman.org/index.htm 这个页面访问到 http://owlman.org/ readme.htm 的,那么后者的该属性值就是 http://owlman.org/index.htm。如果当前页面不来自任何页面,我们是亲自输入 URL 来访问它的,那么该属性值就为 null。
  • anchors 属性:该属性是一个类数组对象,其中存储的是当前页面中所有设置了 name 属性的 <a> 元素。
  • forms 属性:该属性是一个类数组对象,其中存储的是当前页面中所有的 <form> 元素。
  • images 属性:该属性是一个类数组对象,其中存储的是当前页面中所有的 <img> 元素。
  • links 属性:该属性是一个类数组对象,其中存储的是当前页面中所有设置了 href 属性的 <a> 元素。
  • getElementById() 方法:该方法的作用是获取当前页面中指定 id 值的页面元素。如果当前页面中有 id 值相同的元素,就选取其中的第一个元素。例如对于下面的HTML文档:
 <!DOCTYPE html>
         <html lang="zh-cn">
         <head>
           <meta charset="UTF-8">
           <title>浏览器端JS代码测试</title>
           <link rel="stylesheet" type="text/css" href="style.css"/>
           <script type="module" src="03-test.js"></script>
         </head>
         <body>
           <noscript>
             <p>本页面需要浏览器支持或启用JavaScript。</p>
           </noscript>
           <h1>浏览器端的JavaScript</h1>
           <div class="box" id="box_1">
             <p>这是一个 div 区域。</p>
           </div>
           <div class="box" id="box_2">
             <p>这是另一个 div 区域。</p>
           </div>
         </body>
         </html>
如果我们想获取 `id` 值为 `box_1` 的 `` 元素,就可以在其外链的 `js` 文件中编写如下代码:
         const aNode = document.getElementById('box_1');

         // 浅复制
         const shallowCopy = aNode.cloneNode(false);
         console.log(shallowCopy.childNodes.length); // 输出:0

         // 深复制
         const deepCopy = aNode.cloneNode(true);
         console.log(deepCopy.childNodes.length);    // 输出:3
请注意:这里的 `id` 值在大部分浏览器中是严格区分大小写的,但不包括 IE7 及其早期版本。
  • getElementsByName() 方法:该方法的作用是返回一个类数组对象,其中包含了当前页面中所有设置了相同 name 值的元素。我们经常会在处理表单中的单选框时用到它,因为为了让浏览器知道哪些单选框属于同一组互斥性选项,我们会将同一组单选框赋予相同的 name 值。
  • getElementsByTagName() 方法:该方法的作用是返回一个类数组对象,其中包含了当前页面中所有使用了相同标签的元素。例如,上面某些类数组功能的属性可以使用该方法来实现:
        console.log(document.forms == document.getElementsByTagName('form'));
         console.log(document.images == document.getElementsByTagName('img'));
  • getElementsByClassName() 方法:该方法的作用是返回一个类数组对象,其中包含了当前页面中设置了相同 class 属性的元素。众所周知,在 HTML 文档中,元素的 class 属性主要是提供给 CSS 设计样式的,而有时候样式的设置需要 JavaScript 脚本的配合。例如,如果我们想为之前那个 HTML 文档中所有设置了 box 样式的元素注册一个鼠标单击事件,就可以在其外链的 js 文件中这样写:
        const aClassNodes = document.getElementsByClassName('box');
         for(const tmpNode of aClassNodes) {
            tmpNode.onClick = function() {
             tmpNode.className = 'newStyle';
           }
         }

元素节点:

在 DOM 的定义中,元素节点代表的是 XML 或 HTML 文档中的各种页面元素,其 nodeType 的值为 1、nodeName 的值为它们各自对应的页面标签、nodeValue 的值为 null。在 Web 前端开发的语境下,元素节点通常对应着一个具体的 HTML 标签。HTML 的每一种标签都对应着一种类型的元素节点。但在通常情况下,我们在处理元素节点时不需要进行如此细致的分类,熟练掌握一部分通用的属性和方法就足以解决绝大部分问题了。下面就来介绍一下这些属性和方法,首先是任意一种元素节点都有的通用属性。
  • tagName 属性:该属性的作用是返回当前元素节点所对应的 HTML 标签,事实上可以认为这是 nodeName 属性的一个别名。该属性专属于元素节点,无论是在接口语义上,还是在名称上都显得要更直观一些。例如对于之前所用的 HTML 文档中的第一个 <div> 元素,我们可以这样查看它的标签名:
         const aNode = document.getElementById('box_1');
         console.log(aNode.tagName);   // 输出:DIV
需要注意的是,`tagName` 属性返回的 HTML 标签名都是用大写字母来表示的;而对于 XML 标签,它返回的则是文档中实际使用的标签字符。所以,如果我们不清楚自己编写的脚本是用于处理 HTML 标签还是 XML 标签,就必须要对 `tagName` 属性返回的字符串进行统一的大小写转换。
  • id 属性:该属性的作用是返回当前元素节点所对应 HTML 标签的 id 属性。例如对于上面的 aNode 节点,我们可以这样查看它的 id 属性:
        console.log(aNode.id); // 输出:box_1
  • className 属性:该属性的作用是返回当前元素节点所对应 HTML 标签的 class 属性,但由于 class 在 JavaScript 中属于语言本身的关键字,所以只能将其对应属性命名为 className。例如我们可以这样查看 aNode 节点的 className 属性:
         console.log(aNode.className); //输出:box
  • title 属性:该属性的作用是返回当前元素节点所对应 HTML 标签的 title 属性。该属性主要用于对相关的页面元素进行说明,当鼠标指针悬停在该元素上时就会显示 title 属性。例如我们可以这样查看 aNode 节点的 title 属性:
         console.log(aNode.title);
  • lang 属性:该属性的作用是返回当前元素节点所对应 HTML 标签的 lang 属性。该属性主要用于声明相关页面元素及其子元素所采用语言的编码。例如在编写中文网页时,我们通常会这样编写 <html> 标签: <htmllang="zh-cn">。当然,在一般元素节点中很少需要设置该属性。到了 JavaScript 中,我们可以这样查看 aNode 节点的lang属性:
        console.log(aNode.lang);
  • getAttribute() 方法:该方法的作用是读取当前元素的指定属性。它会接收一个字符串类型的实参,用于指定要读取的属性名。需要注意的是,这里的属性名要与当前元素对应的 HTML 标签的属性名相同。例如对于 <div> 标签的 class 属性,我们传递给该方法的实参值就应该是 class,而不是 className。下面,我们来具体演示一下该方法的使用:
         // 获取当前页面中所有<img>标签的src属性
         for(const image of document.images) {
           console.log(image.getAttribute('src'));
         }

         // 获取当前页面中所有<a>标签的href属性
         for(const link of document.links) {
           console.log(link.getAttribute('href'));
         }
另外,需要注意的是,`getAttribute()` 方法的实参值并不区分大小写。换句话说,SRC 和 `src` 指定的是相同的属性名,如果该方法没有找到指定的属性名,就会返回 `null`。
  • setAttribute() 方法:该方法的作用是设置当前元素节点所对应 HTML 标签中指定属性的值。如果指定的属性不存在,那就创建该属性。它接收两个实参,第一个实参是一个用于指定目标属性名的字符串,该实参的用法规则与 getAttribute() 方法的实参完全相同;第二个实参则是目标属性的值。下面,我们来具体演示一下该方法的使用:
         // 为当前页面中所有<img>标签设置src属性
         for(let i = 0; i < document.images.length; ++i) {
           document.images[i].setAttribute('src', i+'.png');
         }

属性节点:

在 DOM 的定义中,属性节点代表的是 XML 或 HTML 文档中各种页面元素的属性,其 nodeType 的值为 2、nodeName 的值为节点所代表的标签属性的名称、 nodeValue 的值为节点所代表的标签属性中存取的数据。在 Web 前端开发的语境中,属性节点通常对应着一个 HTML 标签的属性。属性节点对象主要提供了以下 3 个接口:
  • name 属性:nodeName 属性的别名,用于存取节点所代表的标签属性的名称。
  • value 属性:nodeValue 属性的别名,用于存取节点所代表的标签属性中的数据。
  • specified 属性:该属性值是一个布尔类型的值,用来表示该属性是用脚本代码设置的(值为 true ),还是原本就设置在 HTML 文档中(值为 false )。
下面,我们用脚本创建一个 HTML 标签为 <div> 的元素节点,并在其中演示一下属性节点的使用:
// 用脚本创建新节点
const newNode = document.createElement('div');
document.body.appendChild(newNode);
// 新建属性节点
let attrNode = document.createAttribute('class');
attrNode.value = 'box';
// 为当前元素添加属性
newNode.setAttributeNode(attrNode);
// 重新获取属性节点
attrNode = newNode.getAttributeNode(attrNode.name);
// 以节点对象的形式修改当前元素的属性
attrNode.value = 'newbox';
newNode.setAttributeNode(attrNode);
// 以节点对象的形式删除当前元素的属性
newNode.removeAttributeNode(attrNode);
console.log(attrNode.specified);  // 输出:true
严格来说,属性节点通常并不被视为 HTML 文档所对应 DOM 的一部分,它很少被当作独立的节点来使用。

文本节点

在 DOM 的定义中,文本节点代表的是 XML 或 HTML 文档中各种页面元素中显示的文本,其 nodeType 的值为 3、nodeName 的值为 #text、nodeValue 的值为节点所代表的那段文本。通常情况下,文本节点位于 DOM 树结构的末端,被认为是叶子节点,没有子节点。因此文本节点上的操作基本是一些字符串处理。DOM 为文本节点定义了以下接口。
  • data 属性:nodeValue 属性的别名,用于存取注释节点中的文本。
  • appendData() 方法:该方法的作用是将指定的文本加入当前节点的现有文本的后面。它接收一个字符串类型的实参,用于指定要插入的文本。
  • deleteData() 方法:该方法的作用是将指定的文本从当前节点的现有文本中删除。它接收两个实参,第一个实参用于指定要删除文本的起始位置,第二个实参用于指定要删除文本的字符数。
  • insertData() 方法:该方法的作用是将指定的文本插入当前节点的现有文本中。它接收两个实参,第一个实参用于指定要插入文本在现有文本中的起始位置,第二个实参用于指定要插入的文本。
  • replaceData() 方法:该方法的作用是用指定文本替换掉当前节点的现有文本中的某段文本。它接收 3 个实参,第一个实参用于要替换文本在现有文本中的起始位置,第二个实参用于指定现有文本中要被替换文本的字符数,第三个实参用于指定要替换的文本。
  • splitText() 方法:该方法的作用是在指定位置分割当前节点中的现有文本。它接收一个用于指定分割位置的实参。
  • subSrtingData() 方法:该方法的作用是从当前节点的现有文本中读取某一段指定的文本。它接收两个实参,第一个实参用于指定要读取文本在现有文本中的起始位置,第二个实参用于指定要读取文本的字符数。
下面,我们用脚本创建一个 HTML 标签为 <div> 的元素节点,并在其中演示一下上述接口的使用:
// 用脚本创建新节点
const newNode = document.createElement('div');
newNode.id = 'box_4';
document.body.appendChild(newNode);
// 创建文本节点
const textNode = document.createTextNode('这是box_4中的文本。');
newNode.appendChild(textNode);
console.log(newNode.lastChild.data);  // 输出:这是box_4中的文本。
// 在现有文本后面添加文本
textNode.appendData('你好!');
console.log(newNode.lastChild.data);  // 输出:这是box_4中的文本。你好!
// 在指定位置添加文本
textNode.insertData(0,'test: ');
console.log(newNode.lastChild.data);  // 输出:test: 这是box_4中的文本。你好!
// 读取指定文本
console.log(textNode.substringData(0,'test: '.length));// 输出:test:
// 替换指定文本
textNode.replaceData(0,'test: '.length,'测试:');
console.log(newNode.lastChild.data);  // 输出:测试:这是box_4中的文本。你好!
// 删除指定文本
textNode.deleteData(0,'测试:'.length);
console.log(newNode.lastChild.data);  // 输出:这是box_4中的文本。你好!

注释节点

在 DOM 的定义中,注释节点代表的是 XML 或 HTML 文档中的注释标签,其 nodeType 的值为 8、nodeName 的值为 #comment、nodeValue 的值为节点所代表注释标签中的文本。注释节点对象的接口与文本节点对象基本相同,它可以执行文本节点除 splitText() 方法之外的所有操作。例如对于下面这个带有注释标签的 <div> 标签:
<div id="box_5"><!--这是一个注释。--></div>
注释标签应该是该 <div> 标签的第一个子节点,我们可以通过该子节点的 data 属性来读取其中的注释文本,并用 appendData() 方法添加内容,例如:
const box_5 = document.getElementById('box_5');
console.log(box_5.firstChild.data);      // 输出:这是一个注释。
box_5.firstChild.appendData('测试。');
console.log(box_5.firstChild.data);      // 输出:这是一个注释。测试。

关注公众号「站长严长生」,在手机上阅读所有教程,随时随地都能学习。本公众号由站长亲自运营,长期更新,坚持原创,专注于分享创业故事+学习历程+工作记录+生活日常+编程资料。

公众号二维码
微信扫码关注公众号