DOM扩展
一、选择符API
Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询。
一)querySelector()
在Document和Element类型实例中都可以调用它,在Element类型实例中调用时,
只在该元素的后代元素中查找,该方法接收一个CSS选择符号。
//取得 body 元素 var body = document.querySelector("body"); //取得 ID 为"myDiv"的元素 var myDiv = document.querySelector("#myDiv"); //取得类为"selected"的第一个元素 var selected = document.querySelector(".selected");
二)querySelectorAll()
返回一个NodeList实例。
三)matchesSelecor()
返回一个布尔值。
二、元素的遍历
对于元素间的空格, IE9 及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。这样,
就导致了在使用 childNodes 和 firstChild 等属性时的行为不一致。为了弥补这一差异,而同时又保
持 DOM 规范不变, Element Traversal 规范(www.w3.org/TR/ElementTraversal/)新定义了一组属性。
Element Traversal API 为 DOM 元素添加了以下 5 个属性。
childElementCount:返回子元素(不包括文本节点和注释)的个数。
firstElementChild:指向第一个子元素; firstChild 的元素版。
lastElementChild:指向最后一个子元素; lastChild 的元素版。
previousElementSibling:指向前一个同辈元素; previousSibling 的元素版。
nextElementSibling:指向后一个同辈元素; nextSibling 的元素版。
三、HTML5的DOM扩展
一)与class相关的扩展
1.getElementsByClassName(name):
返回一个NodeList,原生实现,性能优势。
2.classList属性:
HTML5 新增了一种操作类名的方式,可以让操作更简单也更安全,那就是为所有元素添加
classList 属性。这个 classList 属性是新集合类型 DOMTokenList 的实例。与其他 DOM 集合类似,
DOMTokenList 有一个表示自己包含多少元素的 length 属性,而要取得每个元素可以使用 item()方
法,也可以使用方括号语法。此外,这个新类型还定义如下方法。
add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
contains(value):表示列表中是否存在给定的值,如果存在则返回 true,否则返回 false。
remove(value):从列表中删除给定的字符串。
toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
二)焦点管理
document.activeElement:始终会引用DOM中当前获得焦点的元素。
document.hasFocuns():确定文档是否获得了焦点。
三)HTMLDocument的变化
1.document.readyState属性:
该属性有两个值
loading,正在加载文档;
complete,已经加载完文档。
2.页面渲染模式
document.compatMode属性:在标准模式下, document.compatMode 的
值等于"CSS1Compat",而在混杂模式下, document.compatMode 的值等于"BackCompat"。
3.document.head属性
引用页面的head元素
4.document.charset属性
指向页面使用的字符集
四)自定义属性
HTML5中的自定义属性必须以data-开头,可以通过element.dataset访问自定义属性的值
var div = document.getElementById("myDiv"); //取得自定义属性的值 var appId = div.dataset.appId; var myName = div.dataset.myname; //设置值 div.dataset.appId = 23456; div.dataset.myname = "Michael"; //有没有"myname"值呢? if (div.dataset.myname){ alert("Hello, " + div.dataset.myname); }
五)插入标记
虽然 DOM 为操作节点提供了细致入微的控制手段,但在需要给文档插入大量新 HTML 标记的情况
下,通过 DOM 操作仍然非常麻烦,因为不仅要创建一系列 DOM 节点,而且还要小心地按照正确的顺
序把它们连接起来。相对而言,使用插入标记的技术,直接插入 HTML 字符串不仅更简单,速度也更
快。
1.innerHTML
在读模式下, innerHTML 属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应
的 HTML 标记。在写模式下, innerHTML 会根据指定的值创建新的 DOM 树,然后用这个 DOM 树完全
替换调用元素原先的所有子节点。
使用 innerHTML 属性也有一些限制。比如,在大多数浏览器中,通过 innerHTML 插入<script>
元素并不会执行其中的脚本
2.outerHTML
在读模式下, outerHTML 返回调用它的元素及所有子节点的 HTML 标签。在写模式下, outerHTML
会根据指定的 HTML 字符串创建新的 DOM 子树,然后用这个 DOM 子树完全替换调用元素。
<div id="content"> <p>This is a <strong>paragraph</strong> with a list following it.</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div>
如果在<div>元素上调用 outerHTML,会返回与上面相同的代码,包括<div>本身。不过,由于浏
览器解析和解释 HTML 标记的不同,结果也可能会有所不同。(这里的不同与使用 innerHTML 属性时
存在的差异性质是一样的。)
使用 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>元素。
3.insertAdjacentHTML()方法
它接收两个参数:插入位置和要插入的 HTML 文本。第一个参数必须是下列值之一:
"beforebegin",在当前元素之前插入一个紧邻的同辈元素;
"afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
"beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
"afterend",在当前元素之后插入一个紧邻的同辈元素。
4.性能与内存问题
某个元素有一个事件处理程序(或者引用了一个 JavaScript 对象作为属性),在使用前述某个属性将该元
素从文档树中删除后,元素与事件处理程序(或 JavaScript 对象)之间的绑定关系在内存中并没有一并
删除。如果这种情况频繁出现,页面占用的内存数量就会明显增加。因此,在使用 innerHTML、
outerHTML 属性和 insertAdjacentHTML()方法时,最好先手工删除要被替换的元素的所有事件处理
程序和 JavaScript 对象属性 。
使用这几个属性——特别是使用 innerHTML,仍然还是可以为我们提供很多便利的。一般
来说,在插入大量新 HTML 标记时,使用 innerHTML 属性与通过多次 DOM 操作先创建节点再指定它
们之间的关系相比,效率要高得多。这是因为在设置 innerHTML 或 outerHTML 时,就会创建一个 HTML
解析器。这个解析器是在浏览器级别的代码(通常是 C++编写的)基础上运行的,因此比执行 JavaScript
快得多。不可避免地,创建和销毁 HTML 解析器也会带来性能损失,所以最好能够将设置 innerHTML
或 outerHTML 的次数控制在合理的范围内。
5.滚动页面
scroIlntoView()方法
scrollIntoView()可以在所有 HTML 元素上调用,通过滚动浏览器窗口或某个容器元素,调用
元素就可以出现在视口中。如果给这个方法传入 true 作为参数,或者不传入任何参数,那么窗口滚动
之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入 false 作为参数,调用元素会尽可能全部
出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐。)不过顶部不一定平齐