1 节点层次
文档元素:文档的最外层元素,文档中所有其它元素都包含在文档元素中,一个文档中只能有一个文档元素。HTML文档的文档元素始终是<html>
。
DOM树:总共有12种节点类型
序号 | 类型 | 说明 |
---|---|---|
1 | element_node | 元素节点 |
2 | attribute_node | 属性节点 |
3 | text_node | 文本节点 |
4 | cdata_section_node | CDATA片段 |
5 | entity_reference_node | 实体引用 |
6 | entity_node | 实体 |
7 | processing_instruction_node | 处理指令 |
8 | comment_node | 注释节点 |
9 | document_node | 文档节点 |
10 | document_type_node | |
11 | document_fragment_node | |
12 | notation_node |
1 |
|
1.1 Node类型
历史:DOM1 定义的 Node 接口的 JS 实现类 Node
nodeType 属性:JS 的所有节点类型都继承自 Node
类型,因此所有的节点类型都共享着相同的基本属性和方法。
等价的数字(兼容所有浏览器) | Nodetype对应的常量(IE中不存在) |
---|---|
1 | Node.ELEMENT_NODE |
2 | Node.ATTRIBUTE_NODE |
3 | Node.TEXT_NODE |
4 | Node.CDATA_SECTION_NODE |
5 | Node.ENTITY_REFERENCE_NODE |
6 | Node.ENITY_NODE |
7 | Node.PROCESSING_INSTRUCTION_NODE |
8 | Node.COMMENT_NODE |
9 | Node.DOCUMENT_NODE |
10 | Node.DOCUMENT_TYPE_NODE |
11 | Node.DOCUMENT_FRAGMENT_NODE |
12 | Node.NOTATION_NODE |
1 | // 判断节点类型 |
nodeName 和 nodeValue 属性
取值情况取决于节点类型
节点关系
childNodes属性
1 | ☑︎ 值:NodeList对象,一个类数组对象,用于保存一组有序的节点,可以通过位置访问这些节点。 |
1 | var firstChild = someNode.childnodes[0]; |
将NodeList转换为数组
1 | function convertToArray(nodes){ |
parentNode属性
1 | ☑︎ 值:指向文档树中的父节点 |
firstChild属性
1 | ☑︎ 值:指向childNodes列表中的第一个节点 |
lastChild属性
1 | ☑︎ 值:指向childNodes列表中最后一个节点 |
previousSibling属性
1 | ☑︎ 值:指向同一childNodes列表中的上一个节点。 |
nextSibling属性
1 | ☑︎ 值:指向同一childNodes列表中的下一个节点。 |
1 | if(someNode.nextSibling === null){ |
ownerDocument属性
1 | ☑︎ 值:指向整个文档的文档节点 |
hasChildNodes()方法
1 | ☑︎ 返回值:节点包含子节点时返回true;否则返回false |
操作节点(必需先取得父节点,如果节点类型没有子节点将会出错)
appendChild()方法
1 | ☑︎ 用途:向childNodes列表的末尾添加一个节点,相关节点的关系指针都会相应得到更新。 |
1 | var returnode = someNode.appendChild(newNode); |
insertBefore()方法
1 | ☑︎ 用途:将节点放在childNodes列表中某个特定的位置上。 |
1 | //插入后成为最后一个子节点 |
replaceChild()方法
1 | ☑︎ 用途:替换某个节点 |
1 | //替换第一个子节点 |
removeChild()方法
1 | ☑︎ 用途:移除节点 |
1 | //移除第一个子节点 |
其它方法(所有类型节点都有)
cloneNode()
1 | ☑︎ 用途:创建一个节点的副本 |
1 | <ul> |
1 | var deepList = myList.cloneNode(true); |
normalize()方法
1 | ☑︎ 用途:处理文档树中的文本节点,删除空文本节点,合并相邻文本节点 |
1.2 Document类型
- Document 类型
1 | ☑︎ JS通过该类型表示文档 |
- HTMLDocument 类型
1 | ☑︎ 继承自Document类型,表示HTML文档 |
- document对象
1 | ☑︎ HTMLDocuemnt类型的一个实例 |
Document 节点特征
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 0 |
2 | nodeName | #document |
3 | nodeValue | null |
4 | parentNode | null |
5 | ownerDocument | null |
6 | childNodes | 最多一个DocumentType、Element或多个ProcessingInstruction、Comment |
兼容性
| 类型 | 支持访问构造函数和原型 |
| ———— | ——————— |
| Document | FF、Safri、Chrome、Opera |
| HTMLDocument | 所有 |
1.2.1 文档的子节点
body 节点
- document.documentElement(推荐)
- document.childNodes[0]
- document.firstChild
- document.body
1 | <html> |
1 | var html = document.documentElement; //取得对<html>的引用 |
document.docType
说明:访问<!DOCTYPE>
节点
版本 | 处理方式 | document.docType |
---|---|---|
IE8- | 解释为注释并把它作为Comment节点 | null |
IE9+、FF | 作为文档的第一个子节点 DocumentType节点(也可以通过firstChid和childNodes[0]访问到) | |
Safari、Chrome、Opera 不作为文档子节点,不会出现在document.childNodes中 | DocumentType节点 |
1 | var docType = docuemnt.doctype; //取得对<!DOCTYPE>的引用 |
<html>
之外的注释
1 | <!-- 第一条注释 --> |
版本 | 处理方式 | 节点类型 |
---|---|---|
IE8-、Safari3.1+、Opera、Chrome | 只为第一条注释创建注释节点 | 注释节点,document.childNodes中的第一个节点 |
IE9+ | 为两条注释分别创建注释节点 | 注释节点,document.childNodes中的节点 |
FF、Safari3.1- | 完全忽视这两条注释 |
1.2.2 文档信息
HTMLDocument 的实例 document 包含的 Document 对象没有的属性。
document.title属性
1 | ☑︎ 作用:可以取得当前页面的标题,也可以修改当前页面的标题并反映在浏览器的标题栏。 |
1 | //取得文档标题 |
document.URL属性
1 | ☑︎ 作用:取得页面完整的URL |
document.domain属性
1 | ☑︎ 作用:取得页面的域名或通过改变页面中包含的来自其它子域框架或内嵌框架的domain实现跨域通信 |
1 | //假设页面来自www.wrox.com |
docuemnt.referrer属性
1 | ☑︎ 作用:取得链接到当前页面的那个页面的URL |
1 | //取得完整的URL |
1.2.3 查找元素
getElementById()方法
1 | ☑︎ 用途:通过ID获得元素 |
注意
1 | ☑︎ IE7-不区分大小写 |
getElementByTagName()方法
1 | ☑︎ 用途:通过标签名获得元素集合 |
1 | <img src="myimage.gif" name="myimage"> |
1 | var images = document.getElementByTagName('img'); //取得所有图像的集合 |
HTMLCollection 对象
☑︎ namedItem() 方法
1 | ☑︎ 用途:通过元素的name特性取得集合中的项 |
1 | var myImage = images.namedItem('myImage'); |
getElementsByName()
1 | ☑︎ 用途:返回给定name特性的所有元素 |
1 | <fieldset> |
1 | var radios = document.getElementsByName('color'); |
1.2.4 特殊集合(HTMLCollection)
特点:会随着文档的更新而更新
| 集合 | 说明 | 备注 |
| —————- | —————- | —————————————- |
| document.anchors | 文档中所有带name特性的a元素 | |
| document.applets | 文档中所有applet元素 | 不建议使用 |
| document.forms | 文档中所有form元素 | document.getElementByTagName(“form”)得到相同结果 |
| document.images | 文档中所有img元素 | document.getElementByTagName(“img”)得到相同结果 |
| document.lnks | 文档中所有带href特性的a元素 | |
1.2.5 DOM一致性检测
document.implementation属性
可用于检测浏览器实现了DOM的哪些部分
document.implementation.hasFeature()
1 | ☑︎ 参数(2):要检测的DOM功能的名称、版本号 |
1 | var hasXmlDom = document.implementation.hasFeature("XML","1.0"); |
1.2.6 文档写入
1 | 不支持文档写入的情况 |
document.write()
1 | ☑︎ 用途:原样写入输出流到文本 |
document.writeln()
1 | ☑︎ 用途:写入输出流到文本,会自动在字符串的末尾添加一个换行符(\n) |
document.open()
1 | ☑︎ 用途:HTML 文档加载完后使用,用来打开网页输出流 |
document.close()
1 | ☑︎ 用途:关闭输出流 |
1.3 Element类型
节点特征
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 1 |
2 | nodeName | 元素的标签名 |
3 | nodeValue | null |
4 | parentNode | Document或Element |
5 | childNodes | Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference |
属性
☑︎ nodeName属性
1 | 值:标签名 |
☑︎ tagName属性
1 | 值:标签名,比nodeName更清晰 |
1 | <div id="myDiv"></div> |
1 | var div = document.getElementById('myDiv'); |
注意:大小写(HTML中标签名始终都以全部大写表示;XML(XHTML)中与源代码一致)
1 | if(element.tagName.toLowerCase() == 'div'){ |
兼容性
| 浏览器版本 | 行为 |
| —————- | ———————- |
| safari2-、Opera8- | 不能访问Element类型的构造函数 |
| 其它 | 可以访问Element类型的构造函数及其原型 |
1.3.1 HTML元素
属性 | 说明 |
---|---|
id | 元素在文档中的唯一标识符 |
title | 有关元素的附加说明信息,一般通过工具提示条显示出来 |
lang | 元素内容的语言代码,很少使用 |
dir | 语言的方向,“ltr”(从左到右);“rtl”(从右到左) |
className | 为元素指定的CSS类(没有使用class,因为是保留字) |
1 | <div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div> |
1 | var div = document.getElementById("myDiv"); |
所有HTML元素都是由 HTMLElement 或更具体的子类型来表示(斜体指不推荐):
1.3.2 取得特性
getAttribute() 方法
1 | ☑︎ 用途:获得特性值(推荐只在获得自定义特性时使用) |
1 | <div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr" my_special_attribute="hello"></dvi> |
1 | var div = document.getElementById("myDiv"); |
特殊特性
☑ ︎style属性
访问方式 | 返回值 |
---|---|
div.getAttribute(“style”) | CSS文本 |
div.style | 对象 |
☑︎ 事件处理程序
| 访问方式 | 返回值 |
| ————————— | —– |
| div.getAttribute(“onclick”) | 代码字符串 |
| div.onclick | 函数 |
1.3.3 设置特性
setAttribute()方法
1 | ☑︎ 用途:设置或创建特性值(可以自定义,HTML5要求data_前缀) |
1 | div.setAttribute("id", "sometherId"); |
removeAttribute()方法
1 | ☑︎ 用途:彻底删除元素的特性 |
1.3.4 attributes属性
1 | ☑︎ 用途:包含元素的特性,适合用来遍历元素的特性 |
NamedNodeMap对象
☑︎ getNameItem(name): 返回nodeName属性等于name的节点
1 | var id = element.attributes.getNamedItem("id").nodeVlaue; |
☑︎ removeNamedItem(name): 从列表中移除 nodeName 属性等于 name 的节点
1 | var oldAttr = element.attributes.removeNamedItems("id"); |
☑︎ setNamedItem(node): 向列表中添加节点,以节点的 nodeName 属性为索引
1 | element.attributes.setNamedItem(newAttr); |
☑︎ item(pos): 返回位于数字pos位置处的节点
遍历attributes
方式一:全部遍历
1 | ☑︎ 不能保证 attributes 中属性出现的顺序 |
1 | function outputAttributes(element){ |
方式二:只遍历设置了值的属性
1 | function outputAttributes(element){ |
1.3.5 创建元素
document.createElement()方法
1 | ☑︎ 用途:创建节点(会同时设置ownerDocument) |
1 | var div = document.createElement('div'); |
☑︎ 附:IE允许传入完整元素标签
用途:通过指定完整的标签,避开IE7-动态创建元素的某些问题(仅在使用标签名作参数给IE7带来问题时使用)
1 | ☑︎ 不能设置动态创建的 iframe 元素的 name 属性 |
1 | var div = document.createElement("<div id='myNewDiv' class='box'></div>"); |
1.3.6 元素的子节点
遍历子节点
问题:IE会将空白符也解析为子节点
1 | <ul id="myList"> |
解决:遍历时判断节点的类型
1 | for(var i=0,len=element.childNodes.length; i< len;i++){ |
通过标签名取得子节点
注意:会递归各个层次获取子节点
1 | var ul = document.getElementById("myList"): |
1.4 Text类型
节点特征
| 序号 | 属性 | 值 |
| —- | ———- | ——- |
| 1 | nodeType | 3 |
| 2 | nodeName | #text |
| 3 | nodeValue | 包含的文本内容 |
| 4 | parentNode | Element |
| 5 | childNodes | 不支持子节点 |
重要属性 | 说明 |
---|---|
nodeValue属性、data属性 | Text节点中包含的文本 |
length属性 | 包含文本的字符的数目(nodeValue.length、data.length) |
方法 | 说明 |
---|---|
appendData(text) | 将text添加到节点的末尾 |
deleteDate(offset, count) | 从offset指定的位置开始删除count个字符 |
insertData(offset, text) | 重offset指定的位置插入text |
replaceData(offset, count, text) | 用text替换从offset指定的位置开始到offset+count为止处的文本 |
splitText(offset) | 从offset指定的位置开始将文本节点分成两个文本节点 |
substringData(offset,count) | 提取从offset指定的位置开始到offset+count位置处的字符串 |
注意, 默认情况下,每个可以包含内容的元素最多只能有一个文本节点
1 | <div>Hello World!</div> |
1 | var div = docuemnt.getElementByTagName('div')[0]; |
1.4.1 创建文本节点
document.createTextNode() 方法
1 | ☑︎ 用途:创建新文本节点(会同时设置ownerDocument属性) |
1 | var element = document.createElement("div"); |
1.4.2 规范化文本节点
normalize()方法
1 | ☑︎ 调用:定义在Node类型中,所有节点类型都可以调用 |
1 | //创建父节点 |
1.4.3 分割文本节点
spliteText()方法
1 | ☑︎ 调用:定义在Node类型中,所有节点类型都可以调用 |
1 | var element = document.createElement("div"); |
1.5 Comment类型
节点特征
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 8 |
2 | nodeName | #comment |
3 | nodeValue | 注释的内容 |
4 | parentNode | Docuemnt或Element |
5 | childNodes | 不支持子节点 |
重要属性
nodeValue、data:取得注释的内容
1 | <div id="myDiv"><!--A comment--></div> |
1 | var div = document.getElementById("myDiv"); |
方法
和Text继承自相同基类,拥有除splitText()之外的所有字符串操作方法
document.createComment()方法
1 | ☑︎ 用途:创建注释节点 |
1 | var comment = document.createComment("A comment"); |
兼容性
浏览器 | 对注释节点的处理 | 形式 |
---|---|---|
Firefox、Safari、Chrome、Opera | Comment | 可以访问其构造函数和原型 |
IE8 | 标签名为”!”的元素 | 通过getElementByTagName()访问 |
IE9 | HTMLCommentElement |
1.6 CDATASelection类型
节点特征
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 4 |
2 | nodeName | #cdata-section |
3 | nodeValue | CDATA区域中的内容 |
4 | parentNode | Docuemnt或Element |
5 | childNodes | 不支持子节点 |
1 |
1 | 注意 |
1 | <div id="myDiv">![CDATA[This is some content.]]</div> |
方法
document.createCDataSelection()方法
1 | ☑︎ 用途:创建CDATA区域 |
1.7 dcumentType类型
节点特征
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 10 |
2 | nodeName | doctype的名称 |
3 | nodeValue | null |
4 | parentNode | Docuemnt |
5 | childNodes | 不支持子节点 |
属性
☑︎ name: 文档类型的名称,也就是<!DOCTYPE
之后的文本
☑︎ entities: 由文档类型描述的实体的NamedNodeMap对象
☑︎ notations: 由文档类型描述的符号的NamedNodeMap对象
1 |
|
1 | alert(document.doctype.name); //"HTML" |
兼容性
| 版本 | 对DocumentType的支持 | document.doctype的值 |
| —- | —————- | —————— |
| IE8- | 不支持 | null |
| IE9 | 不支持 | 正确赋值 |
1.8 docmentFragment 类型
文档片段介绍
☑︎ 说明:只有该类型没有对应的标记。是一种“轻量级”的文档,可以包含并控制节点,但不会像完整的文档那样占用额外的资源。
☑︎ 用途:不能把文档片段直接添加到文档,但可以将它作为一个“仓库”来使用,即可以在里面保存将来可能添加到文档中的节点。
序号 | 属性 | 值 |
---|---|---|
1 | nodeType | 11 |
2 | nodeName | #docuement-frafment |
3 | nodeValue | null |
4 | parentNode | null |
5 | childNodes | Element、ProcessingInstruction、Comment、Text、CDATASection、EntityReference |
创建
document.createDocumentFragment()方法
☑︎ 用途:创建文档片段
☑︎ 注意:一个节点append文档片段会导致文档片段中的所有节点都被移动到这个节点
1 | <ul id="myList"></ul> |
1 | var fragment = document.createDoocumentFragment(); |
1.9 tr 类型
注意: 不被认为是 DOM 树的一部分
节点特征
| 序号 | 属性 | 值 |
| —- | ———- | ————————————— |
| 1 | nodeType | 11 |
| 2 | nodeName | 特性的名称 |
| 3 | nodeValue | 特性的值 |
| 4 | parentNode | null |
| 5 | 子节点 | HTML中不支持子节点、XML中可以是Text或EntityReference |
属性 | 说明 |
---|---|
nodeName、name | 特性名称 |
nodeValue、value | 特性值 |
specified | 代码中指定了值true;否则为false |
创建
1 | document.createAttribute()方法 |
获得/设置特性
getAttrbuteNode()方法
☑︎ 用途:获得特性节点
☑︎ 参数:特性名称
☑︎ 返回值:特性节点
☑︎ 定义于:Node
setAttrbuteNode()方法
☑︎ 用途:设置特性
☑︎ 参数:特性节点
☑︎ 定义于:Node
2 DOM操作技术
2.1 动态脚本
页面加载时不存在,但将来的某一时刻通过修改 DOM 动态添加的脚本。
方式一:插入外部文件
☑︎ 特点:元素被加入到页面中时才会开始加载
案例一:插入到body最后面
目标
1 | <script type="text/javascript" src = "client.js"></script> |
实现
1 | function loadScript(url){ |
方式二:在页面中插入JS代码
☑︎ 特点:脚本执行后立即可用,将在全局作用域中执行
目标
1 | <script type="text/javascript"> |
实现1:IE会出错(IE将script视为一个特殊的元素,不允许DOM访问其子节点)
1 | var script =document.createElement("script"); |
实现2:IE不会有问题,但Safari3.0-不能正确支持text属性
1 | var script =document.createElement("script"); |
实现3:兼容所有浏览器
1 | function loadScriptString(code){ |
2.2 动态样式
1 | ☑︎ 必需将<link>元素添加到<head>元素中才能保证所有浏览器行为一致 |
方式一
插入外部文件
插入目标
1 | <link rel = "stylesheet" type="text/css" href = "styles.css"> |
实现
1 | function loadStyles(url){ |
方式二
插入包含嵌入式CSS的style节点(解决IE不允许访问style的子节点的问题)
插入目标
1 | <style type="text/css"> |
实现1:未解决 IE 不能访问 style 子节点的问题
1 | function loadStyleString(css){ |
实现2:针对IE访问元素的 styleSheet.cssText
☑︎ 注意:重用同一个style元素进行再次设置或设置为空字符串可能呆滞浏览器崩溃。
1 | function loadStyleString(css){ |
2.3 操作表格
HTMLDOM 还为 table
、tbody
、tr
元素添加了一些属性和方法
| table的属性或方法 | 说明 |
| ————— | ———————— |
| caption | 保存着对caption元素(如果有)的指针 |
| tBodies | 一个tbody元素的HTMLCollection |
| tFoot | 保存着tfoot元素(如果有)的指针 |
| tHead | 保存着对thead元素(如果有)的指针 |
| rows | 是一个表格中所有行的HTMLCollection |
| createTHead() | 创建thead元素,将其放在表格中,返回引用 |
| createTFoot() | 创建tfoot元素,将其放在表格中,返回引用 |
| createCaption() | 创建Caption元素,将其放在表格中,返回引用 |
| deleteTHead() | 删除thead元素 |
| deleteTFoot() | 删除tfoot元素 |
| deleteCaption() | 删除caption元素 |
| deleteRow(pos) | 删除指定位置的行 |
| insertRow(pos) | 向rows集合中的指定位置插入一行 |
tbody的属性或方法 | 说明 |
---|---|
rows | 表格中所有行的HTMLCollection |
deleteRows(pos) | 删除指定位置的行 |
insertRow(pos) | 向rows集合中的指定位置插入一行,返回新插入行的引用 |
tr的属性或方法 | 说明 |
---|---|
cells | 保存着tr元素中单元格的HTMLCollection |
deleteCell(pos) | 删除指定位置的单元格 |
deleteCell(pos) | 删除指定位置的单元格 |
insertCell(pos) | 项cells集合中指定位置插入一个单元格,返回对心插入单元格的引用 |
1 | <table border="1" width="100%"> |
1 | //创建table |
2.4 使用 NodeList
☑︎ 减少对 NodeList 的访问,或将 NodeList 的值缓存起来,因为每次访问都会运行一次基于文档的查询;
☑︎ 遍历 NodeList 最好将其 length 属性值保存在另外一个变量
1 | var divs = document.getElementsByTagName("div"), |