DOM操作技术
1.动态脚本
创建动态脚本的方式:插入外部文件和直接插入javascript代码
在一般浏览器中,可以使用DOM操作生成<script>标签以及通过createTextNode()方法创建其子节点,但IE中,将<script>视为一个特殊元素,不允许DOM访问其子节点,但可以使用<script>标签的text属性来指定javascript代码:
2.动态样式
创建动态样式的方式:通过<link>标签引入外部css文件和通过<style>标签来嵌入CSS代码
动态创建<link>标签时,必须要注意的是,要将<link>标签添加到<head>中而不是<body>
IE中,也将<style>视为一个特殊元素,不允许DOM访问其子节点。
解决这个问题的方法,就是访问元素的styleSheet属性,该属性又有一个cssText属性,可以接受css代码:
3.操作表格
<table>元素是HTML中最复杂的结构之一。为了方便构建表格,HTML DOM还为<table>、
<tbody>和<tr>元素添加了一些属性和方法。
详情:http://www.w3school.com.cn/jsref/dom_obj_table.asp
4.使用NodeList
应该尽量减少访问NodeList的次数
DOM扩展
对DOM的两个主要扩展是Selectors API(选择符API)和HTML5。此外,还有一个不那么引人注目的Element Traversal(元素遍历)规范和一些DOM的专有扩展。
众多Javascript库中最常用的一项功能,就是根据CSS选择符选择与某个模式匹配的DOM元素。
jQuery的核心就是通过CSS选择符查询DOM文档取得元素的引用,从而抛开了getElementById()和getElementsByTagName()。
选择符API
Selectors API Level 1的核心是两个方法:querySelector()和querySelectorAll()。(IE8以下浏览器不支持)
querySelector()接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。
querySelectorAll()方法接收的参数与querySelector()一样,都是一个CSS选择符,但返回的是所有匹配的元素而不仅仅一个元素,返回的是一个NodeList对象,如果没有找到匹配元素,NodeList就是空。
Selectors API Level 2规范为Element类型新增了一个方法matchesSelector()。
这个方法接收一个参数,即CSS选择符,如果调用元素与该选择符匹配,则返回true,否则,返回false.
该方法还未达成统一标准:IE9+通过msMatchesSelector()支持,Firefox 3.6+通过mozMatchesSelector()支持,
Safari 5+和Chrome通过webkitMatchesSelector()支持。
编写一个兼容的包装函数:
元素遍历
Element Traversal API为DOM元素添加了以下5个属性:
childElementCount:返回子元素(不包括文本节点和注释)的个数;
firstElementChild:指向第一个子元素;firstChild的元素版。
lastElementChild:指向最后一个子元素;lastChild的元素版。
previousElementSibling:指向前一个同辈元素;previousSibling的元素版。
nextElementSibling:指向后一个同辈元素;nextSibling的元素版。
利用这些元素就可以不必担心空白文本节点,从而更方便地查找DOM元素。
HTML5
与类相关的扩充
1.getElementsByClassName()方法
接收一个参数,即一个包含一或多个类名的字符串,返回带有指定类的所有元素的NodeList。传入多个类名时,类名的先后顺序不重要。
2.classList属性(仅Firefox3.6+和Chrome支持)
classList属性是新集合类型DOMTokenList的实例。
新类型有如下方法:
add(value):将给定的字符串值添加到列表中。如果值已存在,就不添加了。
contains(value):表示列表中是否存在给定的值,如果存在返回true,反之,false。
remove(value):从列表中删除给定的字符串。
toggle(value):如果列表中已经存在给定值,删除它,如果列表中没有给定值,则添加它。
焦点管理
HTML5添加了辅助管理DOM焦点功能。
document.activeElement属性,这个属性始终会引用DOM中当前获得焦点的元素。
元素获得焦点的方式有页面加载、用户输入和代码中调用focus()方法。
默认情况下,页面刚刚加载完成时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement的值为null
document.hasFocus()方法,用于确定文档是否获得了焦点。
通过检测文档是否获得了焦点,可以知道用户是不是正在与页面交互。
查询文档获知哪个元素获得了焦点,以及确定文档是否获得了焦点,这两个功能最重要的用途是提高web应用的无障碍性。
HTMLDocument的变化
1.readyState属性(document.ready)
该属性有两个值:loading(正在加载文档)和complete(已经加载完文档)
2.兼容模式(document.compatMode)
自从IE6开始区分渲染页面的模式是标准的还是混杂的,检测页面的兼容模式就成为了浏览器的必要功能。
document.compatMode,这个属性就是为了告诉开发人员浏览器采用了哪种渲染模式。
在标准模式下:document.compatMode == “CSS1Compat”
在混杂模式下:document.compatMode == “BackCompat”
3.head属性(仅Chrome和Safari5+支持)
HTML5新增了document.head属性,引用文档的<head>元素
字符集属性
document.charset,可以通过这个属性获取或修改charset属性的值。
自定义数据属性
HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。
可以通过dataset属性来访问自定义属性的值。
dataset属性的值是DOMStringMap的一个实例,也就是一个名值对儿的映射。
插入标记
1.innerHTML属性
在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML标记。
在写模式下,innerHTML会根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点
2.outerHTML属性
在读模式下,outerHTML属性返回调用它的元素及所有子节点的HTML标记。
在写模式下,outerHTML会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。
3.insertAdjacentHTML()方法
这个方法最早出现在IE,它接收两个参数:插入位置和要插入的HTML文本。第一个参数必须是下列的值:
beforebegin、afterbegin、beforeend、afterend
4.内存和性能问题
替换节点可能会导致浏览器的内存占用问题。
scrollIntoView()方法(Chrome不支持)
该方法可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。
专有扩展(浏览器各自专有的扩展,并未写进标准)
1.文档模式,IE8引入的,主要有四种:
IE5:混杂模式;IE7:以IE7标准模式渲染页面;IE8:以IE8标准模式渲染页面;IE9(最高级):以IE9标准模式渲染页面;
2.children属性
这个属性是HTMLCollection的实例,只包含元素中同样还是元素的子节点。
3.contains()方法
判断某个节点是不是另一个节点的后代。
4.插入文本
innerText和outerText
5.滚动
scrollIntoViewIfNeeded(alignCenter)、scrollByLines(lineCount)、scrollByPages(pageCount)
DOM2和DOM3
DOM1级主要定义的是HTML和XML文档的底层结构。DOM2和DOM3级则在这个结构的基础上引入了更多的交互能力,也支持了更高级的XML特性。
DOM2级的主要模块:
DOM2级核心:在1级核心基础上构建,为节点添加了更多方法和属性。
DOM2级视图:为文档定义了基于样式信息的不同视图。
DOM2级事件:说明了如何使用事件与DOM文档交互。
DOM2级样式:定义了如何以编程方式来访问和改变CSS样式信息。
DOM2级遍历和范围:引入了遍历DOM文档和选择其特定部分的新接口。
DOM2级HTML:在1级HTML基础上构建,添加了更多属性、方法和新接口。
DOM变化
DOM2级和3级的目的在于扩展DOM API,以满足操作XML的所有需求,同时提供更好的错误处理和特性检测能力。
DOM3级引入了两个辅助比较节点的方法:isSameNode()和isEqualNode(),这两个方法都接收一个节点参数。
DOM3级还针对DOM节点添加额外数据引入了新方法:setUserData()和getUserData()。
setUserData()接收三个参数
框架的变化
框架和内嵌框架分别用HTMLFrameElement和HTMLIFrameElement表示,它们在DOM2级有个新属性,contentDocument。这个属性包含一个指针,指向表示框架内容的文档对象。
IE8之前版本支持contentWindow的属性,该属性返回框架的window对象,而这个window对象又有一个document属性。
因此,要想在所有浏览器中访问内嵌框架的文档对象,可以使用以下代码:
样式
在HTML中定义样式有三种方法:通过<link/>元素包含外部样式表文件、使用<style/>元素定义嵌入式样式,
以及使用style特性针对特定元素的样式。
检测浏览器是否支持DOM2级定义的CSS能力:
访问元素的样式
任何支持style特性的HTML元素在javascript中都有一个对应的style属性。
通过style属性设置或获取元素的样式。
1.DOM样式属性和方法
”DOM2级样式“规范为style对象定义了如下的属性和方法:
cssText:通过它能够访问到style特性中的CSS代码
length:应用给元素的CSS属性的数量
parentRule:表示CSSRule对象。
getPropertyCSSValue(propertyName):返回给定属性值的CSSValue对象,该对象包含两个属性:cssText和cssValueType。cssValueType属性是一个数值常量,表示值的类型:0表示继承的值,1表示基本的值,2表示值列表,3表示自定义的值。
getPropertyPriority(propertyName):如果给定的属性使用了!important设置,则返回”important”;否则,返回空字符串。
getPropertyValue(propertyName):返回给定属性的字符串值。
item(index):返回给定位置的CSS属性的名称。
removeProperty(propertyName):从样式中删除给定属性。
setProperty(propertyName,value,priority):将给定属性设置为相应的值,并加上优先权标志(“important”或者空字符串)。
2.操作样式表
CSSStyleSheet类型表示的是样式表,包括通过<link>元素包含的样式表和<style>中定义的样式表。
CSSStyle继承自StyleSheet,有如下的属性:
disabled:表示样式是否被禁用的布尔值。·,,
href:如果样式表通过<link>包含的,则是样式表的URL;否则,是null。
meida:当前样式表所支持的所有媒体类型的集合。
ownerNode:指向拥有当前样式表的节点的指针,样式可能是在HTML中通过<link>或<style>引入的。如果当前样式表是其他样式表通过@import导入的,这个属性值为null。IE不支持这个属性。
parentStyleSheet:在当前样式表是通过@import导入的情况下,这个属性是一个指向导入它的样式表的指针。
title:ownerNode中的title属性的值。
type:表示样式表类型的字符串。通常是“type/css”
cssRules:样式表中包含的样式规则的集合。IE不支持
ownerRule:如果样式表是通过@import导入的,这个属性就是一个指针,指向表示导入的规则,否则,值为null。IE不支持
deleteRule(index):删除cssRules集合中指定位置的规则。IE不支持
inserRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持
3.元素大小
1)偏移量
offsetHeight:元素在垂直方向上占用的空间大小。
offsetWidth:元素在水平方向上占用的空间大小。
offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离。
offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离。
2)客户区大小
clientWidth:元素内容区宽度加上左右内边距宽度;
clientHeight:元素内容区高度加上上下内边距宽度;
3)滚动大小
scrollHeight:在没有滚动条的情况下,元素内容的总高度。
scrollWidth:在没有滚动条的情况下,元素内容的总宽度。
scrollLeft:被隐藏在内容区域左侧的像素数。通过设置该属性可以改变元素的滚动位置。
scrollTop:被隐藏在内容区域上方的像素数。通过设置该属性可以改变元素的滚动位置。
4.确定元素大小
getBoundingClientRect()方法,返回矩形对象,包含4个属性:left、top、right和bottom。
(跨浏览器的getBoundingClientRect()方法)
遍历
“DOM2级遍历和范围”模块定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。
这两个类型能够基于给定的起点对DOM结构执行深度优先的遍历操作。
NodeIterator
使用document.createNodeIterator()方法创建实例,这个方法接收4个参数:
root:想要作为搜索起点的树中的节点。
whatToShow:表示要访问哪些节点的数字代码。
filter:是一个NodeFilter对象,或者表示应该接受还是拒绝某种特定节点的函数。
entityReferenceExpansion:布尔值,表示是否要扩展实体引用。这个参数在HTML页面没有用,因为其中的实体引用不能扩展。
NodeIterator的两个主要方法:nextNode()和previousNode(),两者遍历到DOM子树最后一个节点时,都返回null。
遍历<div>中的所有元素:
如果只想返回遍历中遇到的<li>,那么只要使用一个过滤器即可:
var div = document.getElementById(“div1”);
var filter = function(node){
return node.tagName.toLowerCase()==”li”?
NodeFilter.FILTER_ACCEPT:
NodeFilter.FILTER_SKIP;
};
var iterator = document.createNodeIterator(div,NodeFilter.SHOW_ELEMENT,filter,false);
var node = iterator.nextNode();
while(node!=null){
alert(node.tagName);
node = iterator.nextNode;
}
TreeWalker
TreeWalker是NodeIterator的一个更高级版本。使用document.createTreeWalker()方法创建,接收4个与document.createNodeIterator()方法相同的参数。
除了包括nextNode()和previousNode()在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历DOM结构的方法:
parentNode():遍历到当前节点的父节点。
firstChild():遍历到当前节点的第一个子节点。
lastChild():遍历到当前节点的最后一个子节点。
nextSibling():遍历到当前节点的下一个兄弟节点。
previousSibling():遍历到当前节点的上一个兄弟节点。
TreeWalker还有一个属性,名叫currentNode,表示任何遍历方法在上一次遍历中返回的节点。
通过设置这个属性也可以修改遍历继续进行的起点:
范围
DOM2级在Document类型中定义了createRange()方法,让开发人员更方便地控制页面。
每个范围由一个Range类型的实例表示,该实例拥有以下的属性:
startContainer:包含范围起点的节点。
startOffset:范围在startContainer中起点的偏移量。
endContainer:包含范围终点的节点。
endOffset:范围在endContainer中终点的偏移量。
commonAncestorContainer:startContainer和endContainer共同的祖先节点在文档树中位置最深的那个。
1.用DOM范围实现简单选择
使用selectNode()和selectNodeContents()。这两个方法都接收衣蛾参数,即一个DOM节点,然后使用该节点中的信息来填充范围。
selectNode()方法选择整个节点,包括其子节点;而selectNodeContents()方法则只选择节点的子节点。
2.用DOM范围实现复杂选择
使用setStart()和setEnd()方法。这两个方法都接受两个参数:一个参照节点和一个偏移量值。
3.操作DOM范围中的内容
deleteContents():从文档中删除范围所包含的内容。
由于范围选区在修改底层DOM结构时能够保证格式良好,因此即使内容被删除了,最终的DOM结构依旧是格式良好的。
与deleteContents()相似,extractContents()也会从文档中移除范围选区。区别在于extractContents()会返回范围的文档片段。
cloneContents()创建范围对象的一个副本,然后再文档的其他地方插入该副本。
4.插入DOM范围中的内容
insertNode()向范围选区的开始处插入一个节点。
除了向范围内部插入内容之外,还可以环绕范围插入内容,使用surroundContents()方法。这个方法接受一个参数,即环绕范围内容的节点。
在环绕范围插入内容时,后台执行下列步骤:
1)提取出范围中的内容
2)将给定节点插入到文档中原来范围所在的位置上
3)将文档片段的内容添加到给定节点中。
5.折叠DOM范围
所谓折叠范围,就是指范围中未选择文档的任何部分。
使用collapse()方法来折叠范围,这个方法接受一个参数,一个布尔值,表示要折叠到范围的哪一端。true表示折叠到范围的起点,false表示折叠到范围的终点。
也可以通过检测某个范围是否处于折叠状态,来确定范围中的两个节点是否紧密相邻。
通过range.collapse判断
6.比较DOM范围
使用compareBoundaryPoints()方法确定多个范围是否有公共的边界(起点或终点)。
该方法接受两个参数:表示比较方式的常量值和要比较的范围。
返回值如下:如果第一个范围中的点位于第二个范围中的点之前,返回-1;如果两个点相等,返回0;如果第一个范围中的点位于第二个范围中的点之后,返回1。
7.复制DOM范围
cloneRange()方法
8.清理DOM范围
detach()方法