JavaScript学习笔记(9)
来源:互联网 发布:淘宝店铺免费模版 编辑:程序博客网 时间:2024/06/10 20:53
DOM
之前已经学了JS的两大核心——ECMAScript和BOM,还剩最后一个核心内容就是DOM(文档对象模型)。关于DOM,原书(《JavaScript高级程序设计(第3版)》)花了足足三章的篇幅来讲解,可见其重要性。
1 基本概念
DOM是针对HTML和XML文档的一个API,描绘了一个层次化的节点数,允许添加、删除、修改页面的某一部分。
2 节点层次
DOM节点分为几大类型,各类型分别表示文档中不同信息和标记,每个节点都有各自的特点、数据、方法,节点之间又相互关联,形成一个树形结构。
<html> <head> <title>Sample Page</title> </head> <body> <p>Hello World!</p> </body></html>
文档节点是每个文档的根节点,上例中文档节点只有一个根节点——<html>
元素,称之为文档元素,文档元素是文档唯一的最外层元素,文档中的其他元素都包含其中。
每一段标记都可以通过树的一个节点表示。节点类型共有12种,都继承自一个基类。
2.1 Node类型
JS中所有节点类型都继承自Node。每一个节点都有一个nodeType属性,用于表明节点的类型。节点类型由Node类型定义的12个数值常量来表示。
- 1 : Node.ELEMENT_NODE
- 2 : Node.ATTRIBUTE_NODE
- 3 : Node.TEXT_NODE
- 4 : Node.CDATA_SECTION_NODE
- 5 : Node.ENTITY_REFERENCE_NODE
- 6 : Node.ENTITY_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
通过比较即可确定是什么类型:
if (someNode.nodeType == 1) { alert("Element node.")}
2.1.1 nodeName和nodeValue属性
这两个属性包含了节点的具体信息,根据不同类型的节点而有所区别,使用之前最好检测一下节点的类型。对于元素节点,nodeName中保存了标签名,而nodeValue始终为null。
2.1.2 节点关系
节点间关系用文档树来描述,有父节点、子节点、兄弟节点等概念和数据结构是相似的。每个节点都有一个childNodes属性,保存了类似数组的NodeList对象,用于保存一组有序的节点。NodeList是一个基于DOM结构动态变化的结果,可以通过someNode.childNodes[index]
和someNode.childNodes.item(index)
访问。
每个节点都有指针指向之前和之后的节点。
这些关系中,childNode
属性最为简便,可以用它访问文档树的任意节点,hasChildNode()
方法可以检测一个节点是否有子节点。ownerDocument
可以直接访问文档节点。
2.1.3 操作节点
下列四个方法是操作子节点的方法,需要先取得父节点(parentNode属性):
针对所有类型的节点都通用的方法:
2.2 Document类型
Document类型用于表示文档,是非常重要和常用的类型之一。
在浏览器中,document对象是HTMLDocument类型的一个实例,document对象是window对象的一个属性。其特征如下:
- nodeType为9
- nodeName为”#document”
- nodeValue为null
- parentNode为null
- ownerDocument为null
- 子节点可能是DocumentType、Element、ProcessingInstruction、Comment
Document类型可以表示HTML页面或者其他基于XML的文档。document对象是最常见的一个实例。
2.2.1 文档的子节点
可以通过2.1.2的方法访问子节点,还有一些特殊的便捷的访问方法:
<html>
元素, document.body 始终指向<body>
元素, document.doctype 用于访问<!DOCTYPE>
(不过支持程度不高)2.2.2 文档信息
作为HTMLDocument的一个实例,document对象还有一些特殊的属性:
<title>
元素中的文本,可以获取和修改title的值 document.URL 取得完整的URL document.domain 取得域名,出于安全考虑,不同子域的页面不能通过JS通信,将两个页面的domain值设置为相同,则可以相互访问。(例如job.bupt.edu.cn和mail.bupt.edu.cn都设置成bupt.edu.cn才能相互通信) document.referrer 取得来源页面的URL2.2.3 查找元素
2.2.4 特殊集合
常用的一些标签,可以用更快速直接的方法得到:
<a>
元素 forms 所有<form>
元素 images 所有<img>
元素 links 所有带href特性的<a>
元素2.2.5 DOM一致性检测
DOM有多个级别,浏览器版本也众多,因此检测当前浏览器支持的DOM层级尤为重要,如同浏览器检测一样,DOM检测也有其方法。
document.implementation属性与浏览器的DOM实现直接对应,
hasFeature()方法可以检测DOM功能的名称和版本号,最好配合能力检测。
var hasXmlDom = document.implementation.hasFeature("XML","1.0");//如果返回ture,表示当前浏览器支持XML的1.0版本
2.2.6 文档写入
2.3 Element类型
该类型用于表现XML或HTML元素,可以访问该元素的标签名、子节点、特性。其特征如下:
- nodeType为1
- nodeName为元素的标签名,tagName属性也有相同的效果
- nodeValue为null
- parentNode可能为Document或Element
- 子节点可能是Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference
HTML中,tagName返回的值是大写,比较之前要注意转换
2.3.1 HTML元素
HTML元素都由HTMLElement类型及其子类型表示。HTMLElement为HTML元素添加了对应于标准特性的属性:
- id,元素的唯一标识符
- title,元素我的附加说明
- lang,语言代码
- dir,语言的方向(从左至右ltr,从右至左rtl)
- className,对应于CSS类的class特性
可以访问和修改该属性。
var div = document.getElementById("someDiv");alert(div.id); //访问div.id = "newId"; //修改
2.3.2 操作特性
getAttribute()
、setAttribute()
、removeAttribute()
用于获取、设置、删除指定的特性。
一般情况下,标准规定的特性(例如:align,href)都可以直接通过2.3.1的方法获取和设置,getAttribute()这类函数更适合处理自定义的特性。
<div id="someDiv" selfdefined_attr="something">something</div><script> var div = document.getElementById("someDiv"); alert(div.getAttribute("selfdefined_attr")); div.setAttribute("selfdefined_attr","anothor"); div.removeAttribute("selfdefined_attr");</script>
2.3.3 attributes属性
Element类型是使用attributes属性的唯一一个类型,该属性包含一个类似于NodeList的NamedNodeMap集合,元素的每一个特性都有一个Attr节点表示,每个节点都保存在NamedNodeMap当中。下列方法用于操作NamedNodeMap。
attributes属性中包含一系列节点,每个节点的nodeName就是特性的名称,nodeValue是特性值。
var id = element.attributes.getNamedItem("id").nodeValue;var id = element.attributes["id"].nodeValue;element.attributes["id"].nodeValue = "someOtherId";
通常情况下,用2.3.2的方法会更方便,但在遍历元素属性时,attributes属性还是很重要。
function outputAttributes(element) { var pairs = new Array(), attrName, attrValue, i, len; for (i=0,len=element.attributes.length;i<len;i++) { attrName = element.attributes[i].nodeName; attrValue = element.attributes[i].nadeValue; if (element.attributes[i].specified) { //为了适配IE7以下的浏览器 pairs.push(attrName + "=\"" + attrValue + "\""); } } return pairs.join(" ");}
2.3.4 创建元素
document.createElement(tagName)
方法用于创建元素,参数为要创建的元素的标签名。
var div = document.createElement("div"); //创建一个<div>元素div.id = "newId"; div.className="box"; document.body.appendChild(div); //将节点加到文档树中,并被立即显示在浏览器上
2.3.5 元素的子节点
元素可以拥有任意数量的子节点和后代节点,元素的childNodes属性包含了其全部子节点(可能是元素节点、文本节点、注释节点等等)。不同的浏览器处理方式也不尽相同,所以操作之前要检查nodeType属性。
for (var i=0,len=element.childNodes.length;i<len;i++) { if (element.childNodes[i].nodeType == 1){ //do something }}
2.4 Text类型
Text类型用于表示文本节点,包含的可以是纯文本内容,包括转义后的HTML字符,但不包含HTML代码,其特征如下:
- nodeType为3
- nodeName为”#text”
- nodeValue为节点所包含的文本,data属性效果相同
- parentNode为一个Element节点
- 不存在子节点
默认情况下,每个可以包含内容的元素最多有一个文本节点(没有内容就没有文本节点,有内容或空格就会有文本节点)。
相关操作方法:
2.5 Comment类型
用于表示注释,特征如下:
- nodeType为8
- nodeName为”#comment”
- nodeValue为注释内容,data属性效果相同
- parentNode为一个Element节点或Element节点
- 不存在子节点
该类型继承自Text类型,与Text类型相比,没有splitText()
方法,其余方法都有。
2.6 CDATASection类型
用于表示CDATA内容,特征如下:
- nodeType为4
- nodeName为”#cdata-section”
- nodeValue为CDATA内容
- parentNode为一个Element节点或Element节点
- 不存在子节点
该类型继承自Text类型,与Text类型相比,没有splitText()
方法,其余方法都有。
CDATA只会出现在XML文档中,大多数浏览器会将其解析为Comment或Element。
2.7 DocumentType类型
包含与文档doctype信息,特征如下:
- nodeType为10
- nodeName为doctype的名称
- nodeValue为null
- parentNode为一个Document
- 不存在子节点
2.8 DocumentFragment类型
作用类似于“中转站”,将要添加到文档树中的节点先放入DocumentFragment中处理、整合好之后,再一次性加到文档树中,避免浏览器多次渲染,多次刷新。
- nodeType为11
- nodeName为”#document-fragment”
- nodeValue为null
- parentNode为null
- 子节点可以是Element、ProcessingInstruction、Comment、Text、CDATASection、EntityReference
该类型继承了Node的所有方法。
var fragment = document.createDocumentFragment();var ul = document.getElementById("list");var li = null;for (var i=0;i<3;i++) { li = document.createElement("li"); li.appendChild(document.createTextNode("Item " + (i+1))); fragment.appendChild(li);}ul.appendChild(fragment);//一次性添加三个节点
2.9 Attr类型
用于访问特性节点,但实际上使用2.3.2的方法会更简便。
3 DOM操作技术
3.1 动态脚本
可以通过操作DOM,动态的添加外部文件。即加载时不存在该脚本,在页面运行过程中通过修改DOM动态添加。
function loadScriptFile(url){ var script = document.createElement("script"); //创建<script>标签 script.src = "some.js"; document.body.appendChild(script);//将script节点插入文档树,作为body的子节点}function loadScript(code){ var script = document.createElement("script"); //创建<script>标签 try { script.appendChild(document.createTextNode(code)); //将参数(脚本的具体内容)作为子文本节点插入script节点 } catch (ex) { script.text = code; //兼容IE } document.body.appendChild(script);//将script节点插入文档树,作为body的子节点}
执行loadScript(code)
函数的效果实际上和eval()是一样的,这种方式加载的代码会在全局作用域中执行。
3.2 动态样式
方法与加载JS文件和代码类似
3.3 动态表格
表格涉及的元素和标签都比较多,但动态创建一个表格是经常要处理的问题。
DOM提供了规范化的属性和方法用于表格的动态创建。
<table>
定义表格 <caption>
定义表格标题 caption:保存指向caption的指针createCaption():创建caption元素
deleteCaption():删除caption元素
<th>
定义表格的表头 <tr>
定义表格的行 rows:是一个表格中所有行的HTMLCollectioninsertRow(pos):在rows集合中插入一行
deleteRow(pos):删除指定的行
<td>
定义表格单元格 cells:保存着tr元素中单元格的HTMLCollectioninsertCell(pos):向cells集合中的指定位置插入一个单元格
deleteCell(pos):删除指定的单元格
<thead>
定义表格的页眉 tHead:保存指向thead的指针createTHead():创建thead元素
deleteTHead():删除thead元素
<tbody>
定义表格的主体 tBodies:是tbody元素的HTMLCollection <tfoot>
定义表格的页脚 tFoot:保存指向tfoot的指针createTFoot():创建tfoot元素
deleteTFoot():删除tfoot元素
<col>
定义用于表格列的属性 <colgroup>
定义表格列的组 举个例子
var table = document.createElement("table");var caption = table.createCaption("title");var thead = table.createTHead("head");var tbody = document.createElement("tbody");var tfoot = table.createTFoot("foot");table.appendChild(caption);table.appendChild(thead);table.appendChild(tbody);table.appendChild(tfoot);tbody.insertRow(0);tbody.rows[0].insertCell(0);tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1"));tbody.rows[0].insertCell(1);tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2"));tbody.insertRow(1);tbody.rows[1].insertCell(0);tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 3"));tbody.rows[1].insertCell(1);tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 4"));document.body.appendChild(table);
3.4 NodeList
DOM中NodeList、NamedNodeMap、HTMLCollection是三个动态的集合,每当文档结构发生变化,就会更新这个集合。本质上,每次访问NodeList对象时都会实时查询一次DOM树。当想要迭代一个NodeList时,最好先将要使用的相关值保存下来。
var divs = document.getElementsByTagName("div"), i, len, div;for(i=0,len=divs.length; i<len; i++) { div = document.createElement("div"); document.body.appendChild(div);}
- JavaScript学习笔记(9)
- JavaScript学习笔记9
- (9)JavaScript学习笔记 - 对象
- JavaScript学习笔记(三)---JavaScript对象
- javascript学习笔记(一)--初识javascript
- JavaScript 学习笔记(一)
- JavaScript 学习笔记(二)
- JavaScript学习笔记(一)
- JavaScript 学习笔记(一)
- JavaScript 学习笔记(一)
- javascript 学习笔记(1)
- javascript 学习笔记(2)
- javascript 学习笔记(3)
- javascript 学习笔记(4)
- javascript 学习笔记(6)
- JavaScript学习笔记(二)
- JavaScript学习笔记(三)
- javaScript 学习笔记(1)
- RxJava过滤操作符实例
- 概述
- 麦子学院自动化测试-selenium视频教程
- SQL 数据库 学习 022 查询-05 top 的用法 --- 最前面的若干个记录
- win7配置caffe的错误及解决方法
- JavaScript学习笔记(9)
- [kuangbin带你飞]专题五 并查集 F POJ 1417
- Leetcode62: Unique Paths
- hduoj 1312
- 手把手教你做产品经理
- linux shell的iconv
- Codeforces 727D
- Android Service创建USB HOST通信
- 深入理解 Ruby 关键字 yiald