DOM的节点类型

本篇是基于《JavaScript高级程序设计(第3版)》DOM相关章节做的整理与归纳,概述了DOM的常见节点类型及核心要点。本篇适合初级JS开发者阅读以提升对DOM的理解与运用。

0. Node —— DOM基础节点


  • JavaScript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。
  • 每个节点都有一个nodeType属性,用于表明节点的类型。
if(someNode.nodeType === 1){
    alert('Node is an element');    //该节点为元素节点
}
  • 规范中共有12种节点类型(元素节点、属性节点、文本节点、注释、预处理命令。。。),但受到的支持因浏览器而异。当然,最常用的元素节点、属性节点、文本节点等自然是受到广泛且较为统一的支持的。
  • 节点之间的关系:
  • 每个节点都有一个childNodes属性,其中保存着其所有子节点(并非每种节点都有子节点,比如文本节点)。这些子节点用一个NodeList对象表示,这是一个类数组对象,可通过方括号索引或者.item()方法取值,且具有length属性。需要指出的是,NodeList对象是动态的,它会随着实际DOM的变化而时刻变化。
  • 每个节点都有一个parentNode属性,指向其父节点。
  • someNode.firstChildsomeNode.lastChild —— 指向第一个子节点、最后一个子节点。
  • someNode.nextSiblingsomeNode.previousSibling —— 指向下一个兄弟节点、上一个兄弟节点。
  • 通过someNode.hasChildNodes()someNode.childNodes.length判断是否有子节点。
  • 任何节点都不可能同时存在于多个文档中,someNode.ownerDocument指向拥有该节点的文档,即document
  • 节点的操作:
  • appendChild()var node = someNode.appendChild(newNode) —— 添加一个节点到childNodes的最后,并返回该节点。
    注意:如果newNode已经存在于文档中,则这句语句的效果变成移动该节点。
  • insertBefore()var node = someNode.insertBefore(newNode, someNode.firstChild) —— 在someNode.firstChild之前插入一个新节点,并返回插入的节点。
  • replaceChild()var node = someNode.replaceChild(newNode, someNode.firstChild) —— 用newNode替换掉someNode.firstChild,返回newNode
  • removeChild()var node = someNode.removeChild(someNode.lastChild) —— 移除最后一个节点,返回被移除的节点。
  • cloneNode():复制节点(树)的副本。复制出的副本不会指定其父节点,需要手动将其添加到文档中。还要注意,这个方法不会复制onclick=""等JavaScript属性。
    • someNode.cloneNode(true) —— 深复制(复制节点及其子节点树);
    • someNode.cloneNode(false) —— 浅复制(仅复制节点本身);

1. Document类型 —— 文档节点


  • 在浏览器中,document对象是HTMLDocument类型的一个实例,而HTMLDocument继承自Document类型。
  • docuemnt对象作为文档的顶层节点,我们称其为文档节点
  • 文档节点的nodeType等于9
  • 文档节点的nodeName等于'#document'
  • document节点一般拥有如下子节点:
  • DocumentType 文档类型节点 —— 即文档顶部的文档类型声明标签。如:<!DOCTYPE HTML>
  • Element 元素节点 —— 在浏览器中,即<html>...</html>
  • Comment 注释节点 —— 即注释(出现在<html>...</html>外部的注释)。
  • document子节点的访问:
  • document.doctype —— 访问文档类型声明标签。
  • document.documentElement —— 访问文档中的<html>...</html>元素。
  • 扩展:document.body直接指向html中的body元素。
  • document文档信息:
  • document.title —— 文档(页面)标题。
  • document.URL —— 文档(页面)完整的URL,只读。一般情况下与window.location.href相同。
  • document.domain —— 文档(页面)的域名。
  • document.refererer —— 链接到当前文档(页面)的那个页面的URL。
  • document查找元素(HTMLDocument):
  • document.getElementById('myId'):获取文档中id属性值为myId的元素。
  • document.getElementsByTagName('ul'):获取文档中所有的无序列表。返回结果是一个NodeList,不过在HTML中,实际返回的是一个HTMLCollection对象。(HTMLCollection表示元素集合,而NodeList表示节点集合。)
  • document.getElementsByName('myName'):获取文档中所有name属性值为myName的元素。返回结果同样是一个HTMLCollection对象。
  • document特殊集合:
    这些集合都是HTMLCollection对象,对一些常用元素的访问提供快捷方式。
    • document.anchors —— 获取文档中所有带name属性的<a></a>元素。
    • document.links —— 获取文档中所有带href属性的<a></a>元素。
    • document.images —— 获取文档中所有的<img />元素。
  • document.write():文档写入
    可以使用该方法动态地引入外部资源,例如引入一个JS文件。

2. Element类型 —— 元素节点


  • 元素节点的nodeType等于1
  • 元素节点的nodeName等于元素的标签名(大写。与tagName属性返回的值一致)。
  • 所有HTML元素都由HTMLElement或其子类型表示,HTMLElement类型继承自Element类型。
  • HTMLElement类型设定了idclassNametitle等基本属性,因而所有HTML元素都支持这些属性。
  • 不同元素所支持的属性有所不同,原因就在于这些元素由更具体的子类型来表示和实现,而非全部采用HTMLElement类型,比如<button></button>元素由HTMLButtonElement来表示。不过,HTMLElement提供的公共属性对任何元素而言都是不会变的。
  • 对于任何元素的任何属性(包括自定义属性),我们都可以通过getAttribute()setAttribute()removeAttribute()这三个DOM方法进行属性访问、属性设置(新增+更改)、属性删除的操作。
  • 元素节点还拥有一个attributes属性,其值是一个NamedNodeMap对象,类似NodeList。这个attributes包含了某个HTML元素所有的属性信息。
  • 使用document.createElement()可以创建新元素。如:
var newDiv = document.createElement('div');
var newDivIE = document.createElement('<div id=\'myNewDiv\' class=\'box\'></div>');    //除了上面的规范方法,IE还支持这种方式创建新元素

新创建的元素需要使用appendChild()insertBefore()等方法手动添加到DOM树中。

  • 元素的子节点,即someElementNode.childNodes中保存着该元素所有的子节点,这些子节点可能是元素、文本、注释等,在实际操作前最好通过nodeType属性进行检查。

3. Text类型 —— 文本节点


  • 文本节点的nodeType等于3.
  • 文本节点的nodeName等于'#text'
  • 文本节点的nodeValue即为包含的文本内容。
  • 文本节点的父节点是元素节点,没有子节点。
  • 文本节点拥有一个length属性,表示该文本中的字符数。
  • 空格也会生成文本节点。
  • 文本节点的创建:document.createTextNode('文本内容')
  • 浏览器在解析文档时永远不会创建相邻的文本节点,也就是说默认情况下,一个元素节点下最多只能有一个文本节点。
  • 在手动执行某些DOM操作的时候下,会出现多个互为同胞的文本节点,这容易导致混乱。
  • 规范化文本节点:element.normalize()。作用就是将某个元素内的所有相邻文本节点合并为同一个文本节点。normalize()方法由Node类型实现和提供,因此可全局使用。
  • 分割文本节点:var txt = textNode.splitText(3)。分割文本节点是从文本节点中提取数据的一种常用DOM解析技术。

4. Comment类型 —— 注释节点


  • 注释节点的nodeType等于8
  • 注释节点的nodeName等于'#comment'
  • 注释节点的nodeValue即为注释的内容。
  • 注释节点没有子节点。
  • 注释节点的创建:document.createComment('注释内容')

5. DocumentType类型 —— 文档类型声明节点


  • 文档类型声明节点即文档最顶部的类型声明,比如HTML5文档顶部的<!DOCTYPE HTML>
  • 文档类型声明节点的nodeType等于10
  • 文档类型声明节点的nodeName等于文档的类型名。
  • 显然, 文档类型声明节点没有子节点。
  • 浏览器解析文档后,会把该节点对象保存在document.doctype中,因此可通过document.doctype.name直接取得当前文档的类型。

6. DocumentFragment类型 —— 文档片段节点


  • 文档片段节点在文档中没有对应的标记。其作用就是作为一个“仓库”,它可以包含和控制节点(文档片段),但不占用额外的资源,在需要时可将这个“仓库”中的内容添加到文档中。
  • 文档片段节点的nodeType等于11
  • 文档片段节点的nodeName等于'#document-fragment'
  • 文档片段节点没有父节点,因为它只能通过代码创建出来,且始终独立于文档。
  • 文档片段节点无法直接被添加到文档中,我们只能将该节点内部的“文档片段”添加到DOM中。
  • 文档片段节点的创建与使用:
<!-- 假设页面中有一个空的列表,需要动态添加数据 -->
<ul id="myList"></ul>
var fragment = document.createDocumentFragment();
var list = document.getElementById('myList');
var li = null;
for(var i=0; i < 3; i++){
    li = document.createElement('li');
    li.appendChild(document.createTextNode('Item' + (i + 1)));
    fragment.appendChild(li);
}
list.appendChild(fragment);
  • 注意,在执行了list.appendChild(fragment)后,fragment内部的所有子节点都会被删除并转移到list中,但文档片段节点本身 —— fragment仍然存在,这相当于执行了一次剪切操作。

7. Attr类型 —— 属性节点


  • 尽管就技术上而言,属性节点也是节点,但我们一般不将其视作DOM树的一部分。
  • 从HTML的角度来看,属性即元素标签内的特性;从JS的角度看,属性就是元素节点对象实现和提供的相关节点。
  • 属性节点的nodeType等于2.
  • 属性节点的nodeName等于属性名。
  • 属性节点的nodeValue等于属性值。
  • 属性节点在HTML中没有子节点。
  • 属性对象有一个布尔型属性specified用以表示该属性是默认的还是代码指定的。
  • 属性节点的获取、创建与使用:element.getAttributeNode('id')//获取属性节点var attr = document.createAttribute('name')//创建属性节点element.setAttributeNode(attr)//使用属性节点
  • 上面都是对纯粹的属性节点的相关介绍,在实际开发中,对于属性的操作我们一般都使用getAttribute()setAttribute()removeAttribute()这几个更加好用的方法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容