DOM Extensions(DOM扩展)
- 虽然W3C中的DOM规范已经很完备了,为了浏览器能有更多丰富的功能,各个浏览器都有自己对DOM的扩展,有些扩展大多数浏览器厂商都觉得不错,并实现了他们,这些扩展就已经成为名义上的标准了,W3C便会考虑将他们加入正式规范中。
- 指定DOM扩展的主要两个标准是
Selectors API
andHTML5
,其中定义了一些属性和方法,更方便DOM操作,还有Element Traversal
规范中定义了一些属性用于遍历Element节点- 虽然很多DOM扩展W3C都出台了相应规范,仍然还有大量的浏览器专有扩展存在,这些专有属性扩展了浏览器的功能,并有望在未来被加入标准规范。
作为开发者,为什么要知道这些DOM扩展呢?-- DOM扩展,扩展了DOM操作的属性和方法,我们可以用这些扩展的属性方法更高效巧妙的实现业务场景下的实际需求。
一、SELECTORS API 新增选择器API
Selectors API(www.w3.org/TR/selectors-api),是由W3C发起的,用于支持浏览器中的CSS查询,
- 其中 Selectors API Level 1的核心部分定义了两个方法
querySelector()
、querySelectorAll()
,兼容ie8+
用在document、Element类型元素上 - Selectors API Level 2 规范中定义了
matchesSelector()
方法,只能用在Element类型的元素上,判断给定的class或者id是否是当前元素上的属性,兼容ie9+,并且各个浏览器兼容的前缀都不一样,见代码中的对该功能的封装
//get the body element
var body = document.querySelector("body");
//get the element with the ID "myDiv"
var myDiv = document.querySelector("#myDiv");
//get first element with a class of "selected"
var selected = document.querySelector(".selected");
//get first image with class of "button"
var img = document.body.querySelector("img.button");
//get all elements in a (similar to getElementsByTagName("em"))
var ems = document.getElementById("myDiv").querySelectorAll("em");
//get all elements with class of "selected"
var selecteds = document.querySelectorAll(".selected");
//get all elements inside of elements
var strongs = document.querySelectorAll("p strong");
// 对matchesSelector功能兼容各个浏览器的封装
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.");
}
}
if (matchesSelector(document.body, "body.page1")) { // 如果body元素上class属性对应的值中存在page1的class类名,返回true
//do something
}
二、ELEMENT TRAVERSAL 元素遍历
思考如下代码:
/*
- Item 1
*/
var mylist = document.getElementById('mylist');
alert(mylist.childNodes.length); // 3 > ie9+ 其他浏览器
alert(mylist.childNodes.length); // 1 > ie8
在ie8中,空白节点不会被当成text node返回,而高版本浏览器则会返回空白文本节点,这就导致了使用 childNodes
、firstChild
时浏览器表现不一致。
为了解决这个问题,而又同时保持现有的DOM规范, Element Traversal( www.w3.org/TR/ElementTraversal/)定义了一组新的属性,这5个属性如下:
childElementCount
、 firstElementChild
、 lastElementChild
、 previousElementSibling
、 nextElementSibling
这五个方法都是在 Element元素类型上的操作,所以就不用担心 上述空白文本节点(Text类型)导致的问题啦。
兼容性: Internet Explorer 9+, Firefox 3.5+, Safari 4+, Chrome, andOpera 10+.
三、Html5
1. class类相关的扩充
自从HTML4依赖,class属性被用的越来越多,使得js与css的class类交互增加,包括动态的改变class、给定class查询document,为了适应开发人员,Html5规范加入了一些方法,让css的class类使用更便捷。
getElementsByClassName
兼容 Internet Explorer 9+, Firefox 3+,Safari 3.1+, Chrome, and Opera 9.5+
//get all elements with a class containing “username” and “current”, though it
//doesn’t matter if one is declared before the other
var allCurrentUsernames = document.getElementsByClassName("username current");
//get all elements with a class of “selected” that exist in myDiv’s subtree
var selected = document.getElementById(“myDiv”).getElementsByClassName("selected");
className属性、 classList属性
使用className
删除元素的一个属性:(兼容所有浏览器)
/*
...
*/
//remove the “user” class
//first, get list of class names
var classNames = div.className.split(/\s+/);
//find the class name to remove
var pos = -1,
i,
len;
for (i = 0, len = classNames.length; i < len; i++) {
if (classNames[i] == "user") {
pos = i;
break;
}
}
//remove the class name
classNames.splice(i, 1);
//set back the class name
div.className = classNames.join("");
使用 classList
操作元素的class属性值 只兼容到 ie10+
//remove the "disabled" class
div.classList.remove("disabled");
//add the "current" class
div.classList.add("current");
//toggle the "user" class
div.classList.toggle("user");
//figure out what’s on the element now
if (div.classList.contains("bd") && !div.classList.contains("disabled")) {
//do something
)
//iterate over the class names
for (var i = 0, len = div.classList.length; i < len; i++) {
doSomething(div.classList[i]);
}
2. Focus Management 焦点管理
H5新增的两个焦点管理属性:
document.activeElement
- 当前获得了焦点元素的指针
document.hasFocus()
- 是否当前document存在焦点
var button = document.getElementById(“myButton”);
button.focus();
alert(document.activeElement === button); //true
var button = document.getElementById(“myButton”);
button.focus();
alert(document.hasFocus()); //true
支持浏览器 Internet Explorer 4+, Firefox 3+, Safari 4+, Chrome, andOpera 8+
csx.
- activeElement获取当前获取焦点元素、hasFocus()判断当前文档是否有元素获取焦点(eg,是否有input被获取焦点)
-
document.activeElement
默认为document.body,在文档未完全加载前,值为null
- 用户输入input的焦点获取通常通过tab键或者
focus()
方法
3. Changes to HTMLDocument(针对document对象新增3个属性)
HtmlDocument继承Document接口, window的全局对象document对象是 HtmlDocument类型的实例,以下是HTML5针对ocument对象扩展3属性,而这些属性可能在某些浏览器中早就已经作为专有扩展而存在了,这一次只是将其正式加入HTML5规范(以便所有浏览器对照规范去实现)
-
document.readyState
文档状态 loading、 complete
兼容ie4+
-
document.compatMode
浏览器模式
CSS1Compat表示标准模式
BackCompat表示怪异模式(quirks mode)
兼容ie6+
-
document.head
指向head元素的指针
只有 Chrome and Safari 5实现了该属性
eg:
if (document.readyState == “complete”){
//do something
}
if (document.compatMode == “CSS1Compat”){
alert(“Standards mode”);
} else {
alert(“Quirks mode”);
}
var head = document.head || document.getElementsByTagName(“head”)[0];
csx.
document对象新增的3个属性:readyState、compatMode、head
4. 针对字符新增 charset属性
document.charset
获取或者设置文档编码
- 文档编码通常在标签中被指定,也可以通过document.charset属性设置
eg:
- 兼容所有浏览器
alert(document.charset); //”UTF-16” 默认
document.charset = “UTF-8”; // 设置编码
csx.
document.charset属性,获取、设置文档编码
5. 自定义data属性
element.dataset
获取、设置元素上data-属性的值,ie11开始完全兼容该属性
//xxx
var myDiv = document.getElementById("myDiv");
alert(myDiv.dataset.csx); // 获取属性 001
myDiv.dataset.csx = '002'; // 设置属性
alert(myDiv.dataset.csx); // 002
csx.慎用 element元素的dataset属性获取data-开头的属性的值,因为浏览器兼容
6. Markup Insertion插入标记
插入html元素到document,以前做法是新增一些DOM节点,然后将这些节点按顺序插入DOM树,如下,但是,如果要插入大量的html元素,这样操作就显得冗余笨重,为此,HTML5标准化了下列3个方法(innerHTML
、outerHTML
、insertAdjacentHTML
),让元素插入更简单快速。
/*
- Item 1
- Item 2
- Item 3
*/
var myList = document.getElementById("myList");
var newLi = document.createElement("li");
newLi.appendChild(document.createTextNode("new item"));
myList.appendChild(newLi);
innerHTML与outerHTML
innerHTML与outerHTML
- 读取模式下 outerHtml比innerHtml多一层最外面的元素,如下代码
- innerHtml在插入