- 浏览: 45029 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
天使建站:
这里这篇文章更详细 还有完整的实例演示:js跳出循环:brea ...
js学习break、continue、return、witch等语句 -
FX夜归人:
var sm = new Ext.grid.CheckboxS ...
Ext.grid.CheckboxSelectionModel 只能选一行,不能全选和多选
对DOM的两个主要的扩展是Selectors API(选择API)和HTML5。这两个扩展都源自开发社区,而将某些常见做法及API标准化一直是众望所归。此外,还有一个不那么阴人瞩目的Element Traversal(元素遍历)规范,为DOM添加了一些属性。虽然前述两个主要规范(特别是HTML5)已经涵盖了大量的DOM扩展,但专用扩展依然存在。
1、选择符API
Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询。所有实现这一功能的JavaScript库都会写一个基础的CSS解析器,然后再使用已有的DOM方法查询文档并找到匹配的节点。尽管库开发人员在不知疲倦地改进这一过程的性能,但到头来都只能通过运行JavaScript代码来完成查询操作。而把这个功能变成原生API之后,解析和树查询操作可以在浏览器内部通过编译后的代码来完成,极大地改善了性能。
Selectors API Level1的核心是两个方法:querySelector()和querySelectorAll()。在兼容的浏览器中,可以通过Document及Element类型的实例调用它们。目前已完全支持Selectors API Level1的浏览器有IE8+/Firefox3.5+/Safari3.1+/Chrome/Opera10+。
1)querySelector()方法
querySelector()方法接受一个CSS选择符,反悔与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。
通过Document类型调用querySelector()方法时,会在文档元素的方位内查找匹配的元素。而通过Element类型调用querySelector()方法时,只会在该元素的范围内查找匹配的元素。
CSS选择符可以简单也可以复杂,视情况而定。如果传入了不被支持的选择符,querySlector()会抛出错误。
2)querySelectorAll()方法
querySelectorAll()方法接收的参数与querySelector()方法一样,都是一个CSS选择符,但返回的是所有匹配的元素而不仅仅是一个元素。这个方法返回的是一个NodeList的实例。
具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能的问题。
只要传给querySelectorAll()方法的CSS选择符有效,该方法都会返回一个NodeList对象,而不管找到多少匹配的元素。如果没有找到匹配的元素,NodeList就是空的。
与querySelector()类似,能够调用querySelectorAll()方法的类型包括Document、DocumentFragment和Element.要取得返回NodeList中的每一个元素,可以使用item()方法,也可以使用方括号语法。同样与querySelector()方法类似,如果传入了浏览器不支持的选择符或者选择符中有预付错误,querySelectorAll()会抛出错误。
3)matchesSelector()方法
Selectors API Level2规范为Element类型新增了一个方法matchesSelector(),这个方法接受一个参数,即CSS选择符,如果调用元素与该选择符匹配,返回true;否则,返回false。
在取得某个元素引用的情况下,使用这个方法能够方便地检测它是否会被querySelector()或querySelectorAll()方法返回。
截至2011年年中,还没有浏览器支持matchesSelector()方法;不过,也有一些实验性的实现。IE9+通过msMatchesSelector()支持该方法,Firefox3.6+通过mozMatchesSelector()支持该方法,Safari5+和Chrome通过webkitMatchesSelector()支持该方法。因此,如果想使用这个方法,最好是编写一个包装函数。
2、元素遍历
对于元素间的空格,IE9及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。这样,就导致了在使用childNodes和firstChild等属性时的行为不一致。为了弥补这一差异,而同时又保持DOM规范不变,Element Traversal规范新定义了一组属性。
Element Traversal API为DOM元素添加了一下5个属性。
(1)childElementCount:返回子元素(不包括文本节点和注释)的个数。
(2)firstElementChild:指向第一个子元素;firstChild的元素版。
(3)lastElementChild:指向最后一个子元素;lastChild的元素版。
(4)previousElementSibling:指向前一个同辈元素;previousSibling的元素版。
(5)nextElementSibling:指向后一个同辈元素;nextSibling的元素版。
支持的浏览器为DOM元素添加了这些属性,利用这些元素不必担心空白文本节点,从而可以更方便地查找DOM元素了。支持Element Traversal规范的浏览器有IE9+、Firefox3.5+、Safari4+、Chrome和Opera10+。
3、HTML5
HTML5规范则围绕如何使用新增标记定义了大量JavaScript API。其中一些API与DOM重叠,定义了浏览器应该支持的DOM扩展。
1)与类相关的扩充
(1)getElementsByClassName()方法
可以通过document对象及所有HTML元素调用该方法。这个方法最早出现在JavaScript库中,是通过既有的DOM功能实现的,而原生的实现具有极大的性能优势。
getElementsByClassName()方法接收一个参数,即一个包含一或多个类名的字符串,返回带有制定类的所有元素的NodeList.传入多个类名时,类名的先后顺序不重要。
调用这个方法时,只有位于调用元素子树中的元素才会返回。在document对象上调用getElementsByClassName()始终会返回与类名匹配的所有元素,在元素上调用该方法就只会返回后代元素中匹配的元素。
使用这个方法可以更方便地为带有某些类的原价尿素添加事件处理程序,从而不必局限与使用ID或标签名。不过别忘了,因为返回的对象是NodeList,所以使用这个方法与使用getElementsByTagName()以及其他返回NodeList的DOM方法都具有同样的性能问题。
支持getElementsByClassName()方法的浏览器有IE9+、Firefox3+、Safari3.1+、Chrome和Opera9.5+。
(2)classList属性
在操作类名时,需要通过className属性添加、删除和替换类名。因为className中是一个字符串,所以即使只修改字符串一不烦,也必须每次都设置整个字符串的值。如:
<div class="bd user disabled">...</div>
这个<div>元素一共有三个类名。要从中删除一个类名,需要把这三个类名拆开,删除不想要的那个,然后再把其他类名拼成一个新字符串。请看虾米的例子。
为了从<div>元素的class属性中删除“user”,以上这些代码都是必需的。必须得通过类似的算法替换类名并确认元素中是否包含该类名。添加类名可以通过拼接字符串完成,但必须要通过检测确定不会多次添加相同的类名。很多JavaSctipt库都实现了这个方法,见简化这些操作。
HTML5新增了一种操作类名的方式,可以让操作更简单也更安全,那就是为所有元素添加classList属性。这个classList属性是新集合类型DOMTokenList的实例。与其他DOM集合类似,DOMTokenList有一个表示自己包含多少元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号语法。此外,这个新类型还定义如下方法:
(1)add(value):将给定的字符串值添加到列表中。如果值已经不存在,就不添加了。
(2)contains(value):表示列表中是否存在给定的值,如果存在则返回,否则false。
(3)remove(value):从列表中删除给定的字符串。
(4)toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
这样,前面那么多行代码用下面这一行代码就可以代替了:
以上代码能够确保其他类名不受此次修改的影响。其他方法也能极大减少类似基本操作的复杂性。
有了classList属性,除非需要全部删除所有类名,或者完全重写元素的class属性,否则也就用不到className属性了。
支持classList属性的浏览器有Firefox3.6+和Chrome。
2)焦点管理
HTML5也添加了辅助管理DOM焦点的功能。首先就是document.activeElement属性,这个属性始终会引用DOM中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入(通常是通过按Taba键)和在代码中调用focus()方法。
默认情况下,文档刚刚加载完成时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement的值为null。
另外就是新增了documemnt.hasFocus()方法,这个方法用于确定文档是否获得了焦点。
通过检测文档是否获得了焦点,可以知道用户是不是正在与页面交互。
查询文档获知哪个元素获得了焦点,以及确定文档是否获得了焦点,这两个功能最重要的用途是提高Web应用的无障碍性。无障碍Web应用的一个主要标志就是恰当的焦点管理。
实现了这两个属性的浏览器的包括IE4+、Firefox3+、Safari4+、Chrome和Opera8+.
3)HTMLDocument的变化
HTML5扩展了HTMLDocument,增加了新的功能。
(1)readyState属性
IE4最早为document对象引入了readyState属性。Document的readyState属性有两个可能的值:loading,正在加载文档;complete,已经加载完文档。
使用document.readyState的最恰当方式,就是通过它来实现一个指示文档已经加载完成的指示器。在这个属性得到广泛支持之前,要实现这样一个指示器,必须借助onload事件处理程序设置一个标签,表明文档已经加载完毕。
支持readyState属性的浏览器有IE4+、Firefox3.6+、Safari、Chrome和Opera9+.
(2)兼容模式
自从IE6开始区分渲染页面的模式是标准的还是混杂的,检测页面的兼容模式就称为浏览器的必要功能。IE为此给document添加了一个名为compatMode的属性,这个属性就是为了告诉开发人员浏览器采用了哪种渲染模式。在标准模式下,document.compatMode的值等于“CSS1Compat”,而在混杂模式下,document.compatMode的值等于“BackCompat”.
陆续实现这个属性的浏览器有Firefox、Safari3.1+、Opera和Chrome。
(3)head属性
作为对document.body引用文档的<body>元素的补充,HTML5新增了document.head属性,引用文档的<head>元素。要引用文档的<head>元素,可以结合使用这个属性和另一个后备方法。
如果可用,就使用document.head,否则仍然使用getElementsByTagName()方法。
实现document.head属性的浏览器包括Chrome和Safari5。
4)字符集属性
charset属性标识文档中实际使用的字符集,也可以用来指定新字符集。默认情况下,这个属性的值为“UTF-16”,但可以通过<meta>元素、响应头部或直接设置charset属性修改这个值。
另一个属性是defaultCharset,表示根据默认浏览器及操作系统的设置,当前文档默认的字符集应该是什么。如果文档没有使用默认的字符集,那么charset和defaultCharset属性的值可能会不一样。
通过这两个属性可以得到文档使用的字符编码的具体信息,也能对字符编码进行准确的控制。运行适当的情况下,可以保证用户正常查看页面或使用应用。
支持document.charset属性的浏览器有IE、Firefox、Safari、Opera和Chrome。支持document.defaultCharset属性的浏览器有IE、Safari、Chrome.
5)自定义数据属性
HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加,随便命名,只要以data-开头即可。
添加了自定义属性之后,可以通过元素的dataset属性来访问自定义属性的值。dataset属性的值是DOMStringMap的一个实例,也就是一个名值对儿的映射。在这个映射中,每个data-name形式的属性都会有一个对应的属性,只不过属性名没有data-前缀(如,自定义属性是data-myname,那映射中对应的属性就是myname)。
如果需要给元素添加一些不可见的数据以便进行其他处理,那就要用到自定义数据属性。在跟踪链接或混搭应用中,通过自定义数据属性能方便地知道点击来自页面中的哪个部分。
支持自定义数据属性的浏览器有Firefox6+和Chrome。
6)插入标记
使用插入标记的技术,直接插入HTML字符串不仅更简单,速度也更快。以下与插入标记相关的DOM扩展已经纳入了HTML5规范。
(1)innerHTML属性
在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML标记。在写模式下,innerHTML会根据指定的值创建的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。
但是,不同浏览器返回的文本格式会有所不同。IE和Opera会将所有标签转换为大写形式,而Safari、Chrome和Firefox则会原原本本地按照原先文档中(或指定这些标签时)的格式返回HTML,包括空格和缩进。
在写模式下,innerHTML的值会被解析为DOM子树,替换调用元素原来的所有子节点。因为它的值被认为是HTML,所以其中的所有标签都会按照浏览器处理HTML的标准方式转换为元素(转换结果因浏览器而异)。如果设置的值仅是文本而没有HTML标签,那么结果就是设置纯文本。
为innerHTML设置的包含HTML的字符串值与解析后innerHTML的值大不相同。如:
以上操作得到的结果如下:
为innerHTML设置HTML字符串后,浏览器会将这个字符串解析为相应的DOM树。因此设置了innerHTML之后,再从中读取HTML字符串,会得到与设置时不一样的结果。原因在于返回的字符串是根据原始HTML字符串创建的DOM树经过序列化之后的结果。
使用innerHTML属性也有一些限制。比如,在大多数浏览器中,通过innerHTML插入<script>元素并不会执行其中的脚本。IE8及更早版本是唯一能在这种情况下执行脚本的浏览器,但必须满足一些条件。一是必须<script>元素指定defer属性,而是<script>元素必须位于“作用域的元素”(微软所谓)之后。<script>元素被认为是“无作用域的元素”,也就是在页面中看不到的元素,与<style>元素或注释类似。如果通过innerHTML插入的字符串开头就是一个“无作用域的元素”,那么IE会在解析这个字符串前先删除该元素。
在IE中最常用的方式是:
这种方式因为是用隐藏的<input>域而不影响页面布局,故是首选。
大多数浏览器都支持以直观的方式通过innerHTML插入<style>元素,但在IE8及更早版本中,<style>也是一个“没有作用域的元素”,因此也必须给它前置一个“有作用域的元素”。
并不是所用的元素都支持innerHTML属性。不支持innerHTML的元素有:<col>、<solgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<tr>。此外,在IE8及更早版本中,<title>元素也没有innerHTML属性。
无论什么时候,只要使用innerHTML从外部插入HTML,都应该首先以可靠的方式处理HTML。IE8为此提供了window.toStaticHTML()方法,这个方法接收一个参数,即一个HTML字符串;返回一个经过乌海处理后的版本--从源HTML中删除所有脚本节点和事件处理程序属性。
(2)outerHTML属性
在读模式下,outerHTML返回调用它的元素及所有子节点的HTML标签。在写模式下,outerHTML会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。
使用outerHTML属性以下面这种方式设置值:
div.outerHTML = "<p>This is a paragraph.</p>";
这行代码完成的操作与下面这些DOM脚本代码一样:
结果,就是新创建的<p>元素会取代DOM树中的<div>元素。
支持outerHTML属性的浏览器有IE4+、Safari4+、Chrome和Opera8+。Firefox7及之前版本都不支持outerHTML属性。
(3)insertAdjacentHTML()方法
插入标记的最后一个新增方式是insertAdjacentHTML()方法。这个方法最早也是在IE中出现的,它接收两个参数:要插入的位置和要插入的HTML文本。第一个参数必须是下列值之一:
* "beforebegin",在当前元素之前插入一个紧邻的同辈元素;
* "afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
* "beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
* "afterend",在当前元素之后插入一个紧邻的同辈元素。
注意,这些值都必须是小写形式。第二个参数是一个HTML字符串,如果浏览器无法解析该字符串,就会抛出错误。
支持insertAdjacentHTML()方法的浏览器哟IE、Firefox8+、Safari、Opera和Chrome。
(4)内存与性能问题
使用以上方法替换子节点可能会导致浏览器的内存占用问题,尤其是在IE中,问题更加明显。在删除带有事件处理程序或引用了其他JavaScript对象子树时,就有可能导致内存占用问题。假设某个元素有一个事件处理程序(或者引用了一个JavaScript对象作为属性),在使用前述某个属性将该元素从文档树中删除后,元素与事件处理程序(或JavaScript)之间的绑定关系在内存中并没有一并删除。如果这种情况频繁出现,页面占用的内存数量就会明显增加。因此,在使用innerHTML、outerHTML属性和insertAdjacentHTML()方法时,最好先手工删除要被替换的元素的所有事件处理程序和JavaScript对象属性。
不过,使用这几个属性--特别是使用innerHTML,仍然还是可以为我们提供很多便利的。一般来说,在插入大量新HTML标记时,使用innerHTML属性与通过多次DOM操作先创建节点再指定它们之间的关系相比,效率要高得多。这是因为在设置innerHTML或outerHTML时,就会创建一个HTML解析器。这个解析器是在浏览器级别的代码基础上运行的,因此比执行JavaScript快得多。不可避免地,创建和销毁HTML解析器也会带来性能损失,所以最好能够将设置innerHTML或outerHTML的次数控制在合理的范围内。如:
这种每次循环都设置一次innerHTML的做法效率很低。而且,每次循环还要从innerHTML中读取一次信息,就意味着每次循环要访问两次innerHTML。最好的做法是单独构建字符串,然后再一次性地将结果字符串赋值给innerHTML,像下面这样:
这个例子的效率要高的多,因为它只对innerHTML执行了一次赋值操作。
7)scrollIntoView()方法
scrollIntoView()可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果给这个方法传入true作为参数,或者不传入任何参数,那么窗口关东之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入false作为参数,调用元素会尽可能全部出现在视口中。
当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。
支持scrollIntoView()方法的浏览器有IE、Firefox、Safari和Opera。
1、选择符API
Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询。所有实现这一功能的JavaScript库都会写一个基础的CSS解析器,然后再使用已有的DOM方法查询文档并找到匹配的节点。尽管库开发人员在不知疲倦地改进这一过程的性能,但到头来都只能通过运行JavaScript代码来完成查询操作。而把这个功能变成原生API之后,解析和树查询操作可以在浏览器内部通过编译后的代码来完成,极大地改善了性能。
Selectors API Level1的核心是两个方法:querySelector()和querySelectorAll()。在兼容的浏览器中,可以通过Document及Element类型的实例调用它们。目前已完全支持Selectors API Level1的浏览器有IE8+/Firefox3.5+/Safari3.1+/Chrome/Opera10+。
1)querySelector()方法
querySelector()方法接受一个CSS选择符,反悔与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。
通过Document类型调用querySelector()方法时,会在文档元素的方位内查找匹配的元素。而通过Element类型调用querySelector()方法时,只会在该元素的范围内查找匹配的元素。
CSS选择符可以简单也可以复杂,视情况而定。如果传入了不被支持的选择符,querySlector()会抛出错误。
2)querySelectorAll()方法
querySelectorAll()方法接收的参数与querySelector()方法一样,都是一个CSS选择符,但返回的是所有匹配的元素而不仅仅是一个元素。这个方法返回的是一个NodeList的实例。
具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能的问题。
只要传给querySelectorAll()方法的CSS选择符有效,该方法都会返回一个NodeList对象,而不管找到多少匹配的元素。如果没有找到匹配的元素,NodeList就是空的。
与querySelector()类似,能够调用querySelectorAll()方法的类型包括Document、DocumentFragment和Element.要取得返回NodeList中的每一个元素,可以使用item()方法,也可以使用方括号语法。同样与querySelector()方法类似,如果传入了浏览器不支持的选择符或者选择符中有预付错误,querySelectorAll()会抛出错误。
3)matchesSelector()方法
Selectors API Level2规范为Element类型新增了一个方法matchesSelector(),这个方法接受一个参数,即CSS选择符,如果调用元素与该选择符匹配,返回true;否则,返回false。
在取得某个元素引用的情况下,使用这个方法能够方便地检测它是否会被querySelector()或querySelectorAll()方法返回。
截至2011年年中,还没有浏览器支持matchesSelector()方法;不过,也有一些实验性的实现。IE9+通过msMatchesSelector()支持该方法,Firefox3.6+通过mozMatchesSelector()支持该方法,Safari5+和Chrome通过webkitMatchesSelector()支持该方法。因此,如果想使用这个方法,最好是编写一个包装函数。
function matchesSelector(element,selector){ if(element.matchesSelector){ return element.matchesSelector(selector); }else if(element.msMatchesSelector){ return element.msMatchesSelector(selector); }else if(element.mozMatchesSelector){ return element.mozMatchesSelector(selector); }else if(element.webkitMatchesSelector){ return element.webkitMatchesSelector(selector); }else{ throw new Error("Not supported"); } }
2、元素遍历
对于元素间的空格,IE9及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。这样,就导致了在使用childNodes和firstChild等属性时的行为不一致。为了弥补这一差异,而同时又保持DOM规范不变,Element Traversal规范新定义了一组属性。
Element Traversal API为DOM元素添加了一下5个属性。
(1)childElementCount:返回子元素(不包括文本节点和注释)的个数。
(2)firstElementChild:指向第一个子元素;firstChild的元素版。
(3)lastElementChild:指向最后一个子元素;lastChild的元素版。
(4)previousElementSibling:指向前一个同辈元素;previousSibling的元素版。
(5)nextElementSibling:指向后一个同辈元素;nextSibling的元素版。
支持的浏览器为DOM元素添加了这些属性,利用这些元素不必担心空白文本节点,从而可以更方便地查找DOM元素了。支持Element Traversal规范的浏览器有IE9+、Firefox3.5+、Safari4+、Chrome和Opera10+。
3、HTML5
HTML5规范则围绕如何使用新增标记定义了大量JavaScript API。其中一些API与DOM重叠,定义了浏览器应该支持的DOM扩展。
1)与类相关的扩充
(1)getElementsByClassName()方法
可以通过document对象及所有HTML元素调用该方法。这个方法最早出现在JavaScript库中,是通过既有的DOM功能实现的,而原生的实现具有极大的性能优势。
getElementsByClassName()方法接收一个参数,即一个包含一或多个类名的字符串,返回带有制定类的所有元素的NodeList.传入多个类名时,类名的先后顺序不重要。
调用这个方法时,只有位于调用元素子树中的元素才会返回。在document对象上调用getElementsByClassName()始终会返回与类名匹配的所有元素,在元素上调用该方法就只会返回后代元素中匹配的元素。
使用这个方法可以更方便地为带有某些类的原价尿素添加事件处理程序,从而不必局限与使用ID或标签名。不过别忘了,因为返回的对象是NodeList,所以使用这个方法与使用getElementsByTagName()以及其他返回NodeList的DOM方法都具有同样的性能问题。
支持getElementsByClassName()方法的浏览器有IE9+、Firefox3+、Safari3.1+、Chrome和Opera9.5+。
(2)classList属性
在操作类名时,需要通过className属性添加、删除和替换类名。因为className中是一个字符串,所以即使只修改字符串一不烦,也必须每次都设置整个字符串的值。如:
<div class="bd user disabled">...</div>
这个<div>元素一共有三个类名。要从中删除一个类名,需要把这三个类名拆开,删除不想要的那个,然后再把其他类名拼成一个新字符串。请看虾米的例子。
//删除“user”类 //首先,取得类名字符串并拆分成数组 var className = div.className.split(/\s+/); //找到要删除的类名 var pos = -1,i,len; for(i=0,len=className.;ength;i<len;i++){ if(className[i] == "user"){ pos = i; break; } } //删除类名 className.splice(i,1); //把剩下的类名拼成字符串并重新设置 div.className = className.join(" ");
为了从<div>元素的class属性中删除“user”,以上这些代码都是必需的。必须得通过类似的算法替换类名并确认元素中是否包含该类名。添加类名可以通过拼接字符串完成,但必须要通过检测确定不会多次添加相同的类名。很多JavaSctipt库都实现了这个方法,见简化这些操作。
HTML5新增了一种操作类名的方式,可以让操作更简单也更安全,那就是为所有元素添加classList属性。这个classList属性是新集合类型DOMTokenList的实例。与其他DOM集合类似,DOMTokenList有一个表示自己包含多少元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号语法。此外,这个新类型还定义如下方法:
(1)add(value):将给定的字符串值添加到列表中。如果值已经不存在,就不添加了。
(2)contains(value):表示列表中是否存在给定的值,如果存在则返回,否则false。
(3)remove(value):从列表中删除给定的字符串。
(4)toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
这样,前面那么多行代码用下面这一行代码就可以代替了:
div.classList.remove("user");
以上代码能够确保其他类名不受此次修改的影响。其他方法也能极大减少类似基本操作的复杂性。
有了classList属性,除非需要全部删除所有类名,或者完全重写元素的class属性,否则也就用不到className属性了。
支持classList属性的浏览器有Firefox3.6+和Chrome。
2)焦点管理
HTML5也添加了辅助管理DOM焦点的功能。首先就是document.activeElement属性,这个属性始终会引用DOM中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入(通常是通过按Taba键)和在代码中调用focus()方法。
默认情况下,文档刚刚加载完成时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement的值为null。
另外就是新增了documemnt.hasFocus()方法,这个方法用于确定文档是否获得了焦点。
通过检测文档是否获得了焦点,可以知道用户是不是正在与页面交互。
查询文档获知哪个元素获得了焦点,以及确定文档是否获得了焦点,这两个功能最重要的用途是提高Web应用的无障碍性。无障碍Web应用的一个主要标志就是恰当的焦点管理。
实现了这两个属性的浏览器的包括IE4+、Firefox3+、Safari4+、Chrome和Opera8+.
3)HTMLDocument的变化
HTML5扩展了HTMLDocument,增加了新的功能。
(1)readyState属性
IE4最早为document对象引入了readyState属性。Document的readyState属性有两个可能的值:loading,正在加载文档;complete,已经加载完文档。
使用document.readyState的最恰当方式,就是通过它来实现一个指示文档已经加载完成的指示器。在这个属性得到广泛支持之前,要实现这样一个指示器,必须借助onload事件处理程序设置一个标签,表明文档已经加载完毕。
支持readyState属性的浏览器有IE4+、Firefox3.6+、Safari、Chrome和Opera9+.
(2)兼容模式
自从IE6开始区分渲染页面的模式是标准的还是混杂的,检测页面的兼容模式就称为浏览器的必要功能。IE为此给document添加了一个名为compatMode的属性,这个属性就是为了告诉开发人员浏览器采用了哪种渲染模式。在标准模式下,document.compatMode的值等于“CSS1Compat”,而在混杂模式下,document.compatMode的值等于“BackCompat”.
陆续实现这个属性的浏览器有Firefox、Safari3.1+、Opera和Chrome。
(3)head属性
作为对document.body引用文档的<body>元素的补充,HTML5新增了document.head属性,引用文档的<head>元素。要引用文档的<head>元素,可以结合使用这个属性和另一个后备方法。
var head = document.head || document.getElementsByTagName("head")[0];
如果可用,就使用document.head,否则仍然使用getElementsByTagName()方法。
实现document.head属性的浏览器包括Chrome和Safari5。
4)字符集属性
charset属性标识文档中实际使用的字符集,也可以用来指定新字符集。默认情况下,这个属性的值为“UTF-16”,但可以通过<meta>元素、响应头部或直接设置charset属性修改这个值。
另一个属性是defaultCharset,表示根据默认浏览器及操作系统的设置,当前文档默认的字符集应该是什么。如果文档没有使用默认的字符集,那么charset和defaultCharset属性的值可能会不一样。
通过这两个属性可以得到文档使用的字符编码的具体信息,也能对字符编码进行准确的控制。运行适当的情况下,可以保证用户正常查看页面或使用应用。
支持document.charset属性的浏览器有IE、Firefox、Safari、Opera和Chrome。支持document.defaultCharset属性的浏览器有IE、Safari、Chrome.
5)自定义数据属性
HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加,随便命名,只要以data-开头即可。
添加了自定义属性之后,可以通过元素的dataset属性来访问自定义属性的值。dataset属性的值是DOMStringMap的一个实例,也就是一个名值对儿的映射。在这个映射中,每个data-name形式的属性都会有一个对应的属性,只不过属性名没有data-前缀(如,自定义属性是data-myname,那映射中对应的属性就是myname)。
如果需要给元素添加一些不可见的数据以便进行其他处理,那就要用到自定义数据属性。在跟踪链接或混搭应用中,通过自定义数据属性能方便地知道点击来自页面中的哪个部分。
支持自定义数据属性的浏览器有Firefox6+和Chrome。
6)插入标记
使用插入标记的技术,直接插入HTML字符串不仅更简单,速度也更快。以下与插入标记相关的DOM扩展已经纳入了HTML5规范。
(1)innerHTML属性
在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML标记。在写模式下,innerHTML会根据指定的值创建的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。
但是,不同浏览器返回的文本格式会有所不同。IE和Opera会将所有标签转换为大写形式,而Safari、Chrome和Firefox则会原原本本地按照原先文档中(或指定这些标签时)的格式返回HTML,包括空格和缩进。
在写模式下,innerHTML的值会被解析为DOM子树,替换调用元素原来的所有子节点。因为它的值被认为是HTML,所以其中的所有标签都会按照浏览器处理HTML的标准方式转换为元素(转换结果因浏览器而异)。如果设置的值仅是文本而没有HTML标签,那么结果就是设置纯文本。
为innerHTML设置的包含HTML的字符串值与解析后innerHTML的值大不相同。如:
div.innerHTML = "Hello & welcome,<b>\"reader\"!</b>";
以上操作得到的结果如下:
<div id="content">Hello & welcome, <b>"reader"!</b></div>
为innerHTML设置HTML字符串后,浏览器会将这个字符串解析为相应的DOM树。因此设置了innerHTML之后,再从中读取HTML字符串,会得到与设置时不一样的结果。原因在于返回的字符串是根据原始HTML字符串创建的DOM树经过序列化之后的结果。
使用innerHTML属性也有一些限制。比如,在大多数浏览器中,通过innerHTML插入<script>元素并不会执行其中的脚本。IE8及更早版本是唯一能在这种情况下执行脚本的浏览器,但必须满足一些条件。一是必须<script>元素指定defer属性,而是<script>元素必须位于“作用域的元素”(微软所谓)之后。<script>元素被认为是“无作用域的元素”,也就是在页面中看不到的元素,与<style>元素或注释类似。如果通过innerHTML插入的字符串开头就是一个“无作用域的元素”,那么IE会在解析这个字符串前先删除该元素。
在IE中最常用的方式是:
div.innerHTML = "<input type=\"hidden\"><script defer>alert('hi');<\/script>";
这种方式因为是用隐藏的<input>域而不影响页面布局,故是首选。
大多数浏览器都支持以直观的方式通过innerHTML插入<style>元素,但在IE8及更早版本中,<style>也是一个“没有作用域的元素”,因此也必须给它前置一个“有作用域的元素”。
并不是所用的元素都支持innerHTML属性。不支持innerHTML的元素有:<col>、<solgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<tr>。此外,在IE8及更早版本中,<title>元素也没有innerHTML属性。
无论什么时候,只要使用innerHTML从外部插入HTML,都应该首先以可靠的方式处理HTML。IE8为此提供了window.toStaticHTML()方法,这个方法接收一个参数,即一个HTML字符串;返回一个经过乌海处理后的版本--从源HTML中删除所有脚本节点和事件处理程序属性。
(2)outerHTML属性
在读模式下,outerHTML返回调用它的元素及所有子节点的HTML标签。在写模式下,outerHTML会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。
使用outerHTML属性以下面这种方式设置值:
div.outerHTML = "<p>This is a paragraph.</p>";
这行代码完成的操作与下面这些DOM脚本代码一样:
var p = document.createElement("p"); p.appendChild(document.createTextNode("This is a paragraph.")); div.parentNode.replaceChild(p,div);
结果,就是新创建的<p>元素会取代DOM树中的<div>元素。
支持outerHTML属性的浏览器有IE4+、Safari4+、Chrome和Opera8+。Firefox7及之前版本都不支持outerHTML属性。
(3)insertAdjacentHTML()方法
插入标记的最后一个新增方式是insertAdjacentHTML()方法。这个方法最早也是在IE中出现的,它接收两个参数:要插入的位置和要插入的HTML文本。第一个参数必须是下列值之一:
* "beforebegin",在当前元素之前插入一个紧邻的同辈元素;
* "afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
* "beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
* "afterend",在当前元素之后插入一个紧邻的同辈元素。
注意,这些值都必须是小写形式。第二个参数是一个HTML字符串,如果浏览器无法解析该字符串,就会抛出错误。
支持insertAdjacentHTML()方法的浏览器哟IE、Firefox8+、Safari、Opera和Chrome。
(4)内存与性能问题
使用以上方法替换子节点可能会导致浏览器的内存占用问题,尤其是在IE中,问题更加明显。在删除带有事件处理程序或引用了其他JavaScript对象子树时,就有可能导致内存占用问题。假设某个元素有一个事件处理程序(或者引用了一个JavaScript对象作为属性),在使用前述某个属性将该元素从文档树中删除后,元素与事件处理程序(或JavaScript)之间的绑定关系在内存中并没有一并删除。如果这种情况频繁出现,页面占用的内存数量就会明显增加。因此,在使用innerHTML、outerHTML属性和insertAdjacentHTML()方法时,最好先手工删除要被替换的元素的所有事件处理程序和JavaScript对象属性。
不过,使用这几个属性--特别是使用innerHTML,仍然还是可以为我们提供很多便利的。一般来说,在插入大量新HTML标记时,使用innerHTML属性与通过多次DOM操作先创建节点再指定它们之间的关系相比,效率要高得多。这是因为在设置innerHTML或outerHTML时,就会创建一个HTML解析器。这个解析器是在浏览器级别的代码基础上运行的,因此比执行JavaScript快得多。不可避免地,创建和销毁HTML解析器也会带来性能损失,所以最好能够将设置innerHTML或outerHTML的次数控制在合理的范围内。如:
for(var i=0,len=values.length;i<len;i++){ ul.innerHTML += "<li>" + values[i] + "</li>"; //要避免这种频繁操作! }
这种每次循环都设置一次innerHTML的做法效率很低。而且,每次循环还要从innerHTML中读取一次信息,就意味着每次循环要访问两次innerHTML。最好的做法是单独构建字符串,然后再一次性地将结果字符串赋值给innerHTML,像下面这样:
var itemHtml = ""; for(var i=0,len=values.length;i<len;i++){ itemHtml += "<li>"+values[i]+"</li>"; } ul.innerHTML = itemHtml;
这个例子的效率要高的多,因为它只对innerHTML执行了一次赋值操作。
7)scrollIntoView()方法
scrollIntoView()可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果给这个方法传入true作为参数,或者不传入任何参数,那么窗口关东之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入false作为参数,调用元素会尽可能全部出现在视口中。
当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。
支持scrollIntoView()方法的浏览器有IE、Firefox、Safari和Opera。
发表评论
-
COM对象
2014-02-23 15:51 4471、COM COM:The Component Object ... -
客户端检测
2014-02-20 14:12 3239客户端检测是javascript开发中最具争议的一个话题。由于 ... -
javascript基础知识(二)
2014-02-17 11:30 0函数表达式 定义函数的方式有两种,一种是函数声明,另一种就是 ... -
javascript基础知识(一)
2014-02-14 10:33 5121、Boolean类型 var flaseObject = n ... -
鼠标定位
2013-11-25 15:10 577当我们单击或移动鼠标时,一般都需要获得鼠标位置,其位置可分为C ... -
js 添加事件 attachEvent 和 addEventListener 的用法
2013-11-25 10:42 699一般我们在JS中添加事件,是这样子的 1 obj.onclic ... -
JavaScript数组
2013-11-21 11:05 495JavaScript数组是有序集合,它包含堆栈、队列等数 ... -
再论call和apply
2013-11-11 15:34 439因为继续研究Ajax Framework的原因,更多的接触了c ... -
全面理解javascript的caller,callee,call,apply概念(修改版)
2013-11-11 15:31 865在提到上述的概念之前 ... -
IE下使用excanvas.js的注意事项
2013-10-16 09:53 1276下载网址:http://code.google.com/p/e ... -
JS判断浏览器类型方法
2013-10-16 09:42 2187方法一: 2009-05-29 23:01 ... -
网站如何做到 jQuery-free?
2013-06-14 14:45 904本文转载自ITeye新闻月 ... -
js学习break、continue、return、witch等语句
2013-04-25 17:23 20471、break语句 break语句会使运行的程序立刻退出包含在 ... -
js == 与 === 的区别
2013-04-18 17:22 673”==”与”===”是不同 ... -
javascript eval和JSON之间的联系
2012-12-27 13:13 767javascript eval和JSON之间的联系 如果您想 ...
相关推荐
#### DOM扩展库解析XML 在PHP环境中,DOM扩展库为解析和操作XML文档提供了一套全面的功能: 1. **加载XML文档**:首先使用`DOMDocument`类加载XML文档。 ```php $dom = new DOMDocument(); $dom->load('example...
PHP使用自带DOM扩展进行元素匹配的原理解析涉及到PHP中DOM扩展库的使用。DOM扩展库是PHP提供的用于解析和操作HTML和XML文档的一个扩展。它允许开发者通过程序控制HTML或XML文档的结构、内容和样式。本文将详细介绍...
本人自己翻译的Burp Suite 专业版的中文手册,陆续更新,请期待
给出了支持DOM核心模型和多种DOM扩展规范的XML编辑器ONCEXMLEditor的实现。ONCEXMLEditor具有高效的XML验证和序列化性能,同时提供给用户多种功能,包括按需遍历文档、提供上下文感知的编写环境、实时纠错、灵活的装载...
unwrapped.js 以性能为重点的简单Javascript DOM扩展和实用程序。 对于那些jQuery太多的时代。浏览器支持Chrome 42+ Firefox 38+ Internet Explorer 11+ Safari 8+辅助功能id ( id ) // returns Elementclasses ( ...
PHP的DOM扩展提供了一系列的类和函数,用于创建、遍历和修改DOM对象。在给定的“php dom 解析类和函数文件封装”主题中,我们可以深入探讨PHP如何利用DOM进行HTML解析。 `simple_html_dom`是PHP的一个开源库,它...
此库的实现基于PHP的DOM扩展,但提供了一套更符合Web开发者习惯的API。 二、核心功能 1. **HTML加载**:Simple HTML DOM允许从字符串或者文件路径加载HTML内容,并转化为可操作的对象结构。 2. **选择器查询**:...
此外,标签“源码”和“工具”暗示了这个话题可能包含一些实用的代码示例和可能的工具库,如PHP的DOM扩展,或者是帮助简化DOM操作的第三方库,如PHP Simple HTML DOM Parser。这些工具可以简化对HTML文档的处理,...
在PHP中,DOM扩展提供了PHP HTML DOM,它允许我们解析HTML文档并对其进行操作。 标题“HtmlDom.rar_HTML dom_PHP HTMLdom”指出这个压缩包文件包含与HTML DOM和PHP中处理DOM相关的资源。文件“HtmlDom.chm”很可能...
事件DOM扩展了对事件处理的支持,使得JavaScript可以响应用户或系统的各种交互。在JavaScript DOM2中,事件处理分为两个级别:事件目标和事件流。事件目标是指事件实际发生的地方,而事件流包括冒泡和捕获两种模式。...
XMLDOM.rar是一个与PHP DOM相关的压缩包,主要涉及如何使用PHP的DOM扩展来处理大量XML数据。PHP DOM(Document Object Model)是PHP中一个强大的工具,它允许开发者以树形结构解析XML文档,并能方便地对其进行修改、...
在Laravel4中,为了处理HTML DOM,我们可以使用一个名为"htmldom"的第三方库,这个库基于PHP的DOM扩展,提供了一个更友好的接口。虽然Laravel4已经比较老,但它仍然具有广泛的应用,并且与"htmldom"库的集成可以增强...
本文主要讲述如何通过JavaScript来扩展DOM元素的功能,以增强元素的可用性和灵活性。在文章中,作者提出了一个实际问题:当使用标准的DOM属性如onclick时,代码可能在不同浏览器上存在兼容性问题。针对这一问题,...
8. **DOM扩展**:易语言社区提供了许多第三方模块,如XML库,它们可能提供了更丰富的DOM操作功能,比如XPath查询,或者更方便的节点遍历接口。 掌握易语言中的DOM操作,不仅可以帮助你处理XML和HTML文档,还可以在...
【第20章 DOM进阶1】主要涵盖了DOM(Document Object Model)的深入学习,包括DOM类型、DOM扩展以及DOM操作。DOM是一种编程接口,它允许程序和脚本动态更新、添加、删除和改变HTML或XML文档的结构、内容和样式。 ...
六、DOM扩展 随着Web技术的发展,DOM接口也在不断扩展,如MutationObserver用于监听DOM变化,以及Shadow DOM用于组件化开发。书中会介绍这些新特性,帮助读者跟上Web发展的步伐。 七、实战项目 书中的实战项目部分...
在这一教程中,我们将深入探讨如何使用PHP的DOM扩展来创建和操作XML文件。XML(eXtensible Markup Language)是一种用于存储和传输数据的标准格式,它具有结构化、自描述性的特点,使得数据易于解析和处理。PHP DOM...