选择符API
这个API存在的主要目的就是让JS原生支持CSS查询。
querySelector()
这个方法接收一个CSS选择符,返回与该模式匹配的第一个元素或null。
var body = document.querySelector("body");
querySelectorAll()
这个方法同样接收一个CSS选择符,以静态NodeList的形式返回所有匹配的元素。
var strongs = document.querySelectorAll("p strong");
strong = strongs[i];
strong = strongs.item(i);
matchesSelector()
接收一个CSS选择符,并返回调用元素与该选择符是否匹配。
if (document.body.matchesSelector("body.page1")){
//true
}
元素遍历
由于空白text类型节点的问题,childNodes里面会包含空的文本节点。这导致遍历元素很不方便。于是有了这几个属性,它们都只返回真正的元素:
- childElementCount
- firstElementChild
- lastElementChild
- previousElementSibling
- nextElementSibling
这样一来遍历元素就不用判断节点类型了:
var i,
len,
child = element.firstElementChild;
while(child != element.lastElementChild){
processChild(child);
child = child.nextElementSibling;
}
HTML5
与类相关的扩充
getElementsByClassName()
接收一个或多个类名,返回动态NodeList。
var selected = document.getElementById("myDiv").getElementsByClassName("username current");
classList
这个是便于大家添加,删除类名的,之前使用className属性获得的是一个字符串,每次要改变都得找出要改的那个,删除或改变,再拼出新的字符串。有了这个属性就方便多了。
classList是新的类型DOMTokenList的实例。提供了4个方法:
- add(value)
- contains(value)
- remove(value)
- toggle(value) 如果存在就删除,不存在就添加
div.classList.add("current");
div.classList.toggle("user");
div.classList.remove("user");
if (div.classList.contains("bd")) {
}
焦点管理
添加了document.activeElement属性,这个属性始终引用DOM中当前获得焦点的元素。默认情况下,当文档刚刚加载完成时,这里面保存的是body元素,加载过程中是null。
添加了document.hasFocus()方法,用于确定元素是否获得焦点。
var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
alert(document.hasFocus()); //true
HTMLDocument的变化
readyState属性
指示文档是否加载完成,有两个可能的值:loading和complete。
if (document.readyState == "complete"){
}
兼容模式
区分渲染页面的模式是标准的还是混杂的。属性为document.compatMode。标准模式时值为CSS1Compat,混杂模式时为BackCompat。
if (document.compatMode == "CSS1Compat"){
alert("Standards mode");
} else {
alert("Quirks mode");
}
head属性
像body一样可以直接访问了document.head。
var head = document.head || document.getElementsByTagName("head")[0];
字符集属性
HTML5新增了几个与文档字符集有关的属性
charset表示文档中实际使用的字符集,默认为UTF-16,可以通过
<meta charset="UTF-8">
来设置,或者响应头部,或者在JS中直接设置这个属性。
alert(document.charset);
alert(document.defaultCharset);
另一个属性是defaultCharset,代表根据默认浏览器设置,字符集应该是什么。
自定义数据属性
使用data-加自定义名,可以定义自己的节点特性,在JS里使用dataset访问,这个属性的值是一个DOMStringMap的一个实例,也就是一个键值对的映射。访问时不用带data-前缀。
var div = document.getElementById("myDiv");
var appId = div.dataset.appId;
var myName = div.dataset.myname;
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
alert(div.dataset.myname);
alert(div.dataset.appId);
//就算原来没有写在DOM里的也可以设置,会同步到DOM里
div.dataset.haha = "hahaha";
alert(div.dataset.haha);
插入标记
使用插入标记,可以直接插入HTML字符串来构建DOM树。
innerHTML
在读模式下,返回与调用元素所有子节点对应的HTML标记的字符串。
在写模式下则会根据指定的值创建新的DOM树,然后替换调用元素所有子节点。
alert(document.body.innerHTML);
var div = document.getElementById("myDiv");
div.innerHTML = "<p>balalala</p><button>balalala</button>";
虽然绝大部分浏览器不支持在innerHTML中添加script节点,但是IE8是支持的,虽然有些特殊,要插入在有作用域的元素后。而且通过onclick等事件插入可执行的代码也是可能的。所以为了安全,在使用innerHTML时一定要注意安全。
style元素是被支持的。在IE8中有些特殊,要插入在有作用域的元素后。
//style元素是被支持的。在IE8中有些特殊,要插入在有作用域的元素后。
//失败
div.innerHTML = "<style type=\"text/css\">body {background-color: red; }</style>";
//成功
div.innerHTML = "_<style type=\"text/css\">body {background-color: red; }</style>";
//成功
div.innerHTML = "<input type=\"hidden\"><style type=\"text/css\">body {background-color: red; }</style>";
outerHTML
这个就是不止替换子元素,调用元素本身也被替换。
insertAdjacentHTML()
这个方法是在指定位置插入HTML文本,可以指定的位置有4个:
- before begin:在当前元素之前插入一个同辈元素
- after begin:插入在当前元素的所有子元素之前,作为当前元素的子元素
- beforeend:插入在当前元素的所有子元素之后,作为当前元素的子元素
- afterend:在当前元素之后插入一个同辈元素
element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
内存与性能问题
在使用这个几个方法替换节点时,节点如果有一个事件处理程序或者引用了其他对象作为属性,这些东西可能还在内存中。所以最好先手动删除这些。
不过在插入新元素时,这个方法不管在编写上还是执行上都比我们使用DOM操作要高效的多,在执行这个方法时会创建一个HTML解析器,这个通常时浏览器级别的C++代码。
但是创建和销毁HTML解析器是要开销的,所以尽量减少调用次数,将字符串一次拼好在调用。
scrollIntoView()
div.scrollIntoView();
这个就是让屏幕滚动到这个元素所在的位置让大家能看见。传入true则尽量元素顶部与屏幕平齐,传入false则尽量多显示元素。
把当前元素设置为焦点也可以达到这个效果。
专有拓展
这些都是各个浏览器自己实现的,有的很普遍,有的很不普适。
文档模式
决定了可以使用什么功能,IE5,IE7,IE9等。
可以强制浏览器以什么方式渲染,通过HTTP头部的 X-UA-Compatible或meta标签。
<meta http-equiv="X-UA-Compatible" content="IE=IEVersion">
其中IEVersion可以是Edge、EmulateIE9、EmulateIE8、EmulateIE7、9、8、7、5。
JS里也可以获取,IE中才有貌似。
var mode = document.documentMode;
children属性
只返回元素子节点,没有乱七八糟的文本节点
var childCount = element.children.length;
contains()方法
一个节点是不是另一个的后代
alert(document.documentElement.contains(document.body)); //true
插入文本
innerText
<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>
对content使用innerText读:
This is a paragraph with a list following it.
Item 1
Item 2
Item 3
写的话就覆盖所有子节点,且会进行HTML编码去掉HTML标签避免生成多个节点。这个可以用来过滤用户输入哦。
有的浏览器不支持这个,但是支持textContent。
function getInnerText(element){
return (typeof element.textContent == "string") ?
element.textContent : element.innerText;
}
function setInnerText(element, text){
if (typeof element.textContent == "string"){
element.textContent = text;
} else {
element.innerText = text;
}
}
outerText
读时与innerText一样,写时覆盖调用节点。