querySelector()方法css
接收一个 CSS 选择符,返回与该模式匹配的第一个元素,若是没有找到匹配的元素,返回 nullhtml
//取得 body 元素 var body = document.querySelector("body"); //取得 ID 为"myDiv"的元素 var myDiv = document.querySelector("#myDiv"); //取得类为"selected"的第一个元素 var selected = document.querySelector(".selected"); //取得类为"button"的第一个图像元素 var img = document.body.querySelector("img.button");
经过 Document 类型调用 querySelector()方法时,会在文档元素的范围内查找匹配的元素。而经过 Element 类型调用 querySelector()方法时,只会在该元素后代元素的范围内查找匹配的元素html5
若是传入了不被支持的选择符,querySelector()会抛出错误node
querySelectorAll()方法web
接收一个 CSS 选择符,返回的一个 NodeList 的实例,包含匹配的全部元素,若是没有找到匹配的元素,NodeList 就是空的api
可以调用 querySelectorAll()方法的类型包括 Document、DocumentFragment 和 Element浏览器
//取得某<div>中的全部<em>元素(相似于 getElementsByTagName("em")) var ems = document.getElementById("myDiv").querySelectorAll("em"); //取得类为"selected"的全部元素 var selecteds = document.querySelectorAll(".selected"); //取得全部<p>元素中的全部<strong>元素 var strongs = document.querySelectorAll("p strong");
要取得返回的 NodeList 中的每个元素,可使用 item()方法,也可使用方括号语法安全
var i, len, strong; for (i=0, len=strongs.length; i < len; i++){ strong = strongs[i]; //或者 strongs.item(i) strong.className = "important"; }
若是传入了浏览器不支持的选择符或者选择符中有语法错误,querySelectorAll()会抛出错误app
matchesSelector()方法性能
接收一个参数,即 CSS 选择符,若是调用元素与该选择符匹配,返回 true;不然,返回 false
if (document.body.matchesSelector("body.page1")){ //true }
兼容性:
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")){ //执行操做 }
childElementCount:返回子元素(不包括文本节点和注释)的个数
firstElementChild:指向第一个子元素;firstChild 的元素版
lastElementChild:指向最后一个子元素;lastChild 的元素版
previousElementSibling:指向前一个同辈元素;previousSibling 的元素版
nextElementSibling:指向后一个同辈元素;nextSibling 的元素版
//跨浏览器遍历某元素的全部子元素的通常方法 var i, len, child = element.firstChild; while(child != element.lastChild){ if (child.nodeType == 1){ //检查是否是元素 processChild(child); } child = child.nextSibling; } //而使用 Element Traversal 新增的元素 var i, len, child = element.firstElementChild; while(child != element.lastElementChild){ processChild(child); //已知其是元素 child = child.nextElementSibling; }
与类相关的扩充
getElementsByClassName()方法:接收一个参数,即一个包含一或多个类名的字符串,返回带有指定类的全部元素的 NodeList
//取得全部类中包含"username"和"current"的元素,类名的前后顺序无所谓 var allCurrentUsernames = document.getElementsByClassName("username current"); //取得 ID 为"myDiv"的元素中带有类名"selected"的全部元素 var selected = document.getElementById("myDiv").getElementsByClassName("selected");
classList 属性
概念:一种操做类名的方式,可让操做更简单也更安全,那就是为全部元素添加classList 属性。这个 classList 属性是新集合类型 DOMTokenList 的实例。与其余 DOM 集合相似,DOMTokenList 有一个表示本身包含多少元素的 length 属性,而要取得每一个元素可使用 item()方法,也可使用方括号语法
方法:
add(value):将给定的字符串值添加到列表中。若是值已经存在,就不添加了 contains(value):表示列表中是否存在给定的值,若是存在则返回 true,不然返回 false remove(value):从列表中删除给定的字符串 toggle(value):若是列表中已经存在给定的值,删除它;若是列表中没有给定的值,添加它
有了 classList 属性,除非你须要所有删除全部类名,或者彻底重写元素的 class 属性,不然也
就用不到 className 属性了
//<div class="bd user disabled">...</div> //删除"disabled"类 div.classList.remove("disabled"); //添加"current"类 div.classList.add("current"); //切换"user"类 div.classList.toggle("user"); //肯定元素中是否包含既定的类名 if (div.classList.contains("bd") && !div.classList.contains("disabled")){ //执行操做 ) //迭代类名 for (var i=0, len=div.classList.length; i < len; i++){ doSomething(div.classList[i]); }
焦点管理
document.activeElement 属性:始终会引用 DOM 中当前得到了焦点的元素。元素得到焦点的方式有页面加载、用户输入(一般是经过按 Tab 键)和在代码中调用 focus()方法
var button = document.getElementById("myButton"); button.focus(); alert(document.activeElement === button); //true
document.hasFocus()方法:用于肯定文档是否得到了焦点
var button = document.getElementById("myButton"); button.focus(); alert(document.hasFocus()); //true
HTMLDocument的变化
Document 的readyState 属性:
if (document.readyState == "complete"){ //执行操做 }
兼容模式:document 添加了一个名为 compatMode 的属性,为了告诉开发人员浏览器采用了哪一种渲染模式
if (document.compatMode == "CSS1Compat"){ alert("Standards mode");//标准模式下,值等于"CSS1Compat" } else { alert("Quirks mode");//混杂模式下,值等于"BackCompat"。 }
head 属性:做为对 document.body 引用文档的元素的补充,引用文档的元素
var head = document.head || document.getElementsByTagName("head")[0];
字符集属性
charset 属性:表示文档中实际使用的字符集,也能够用来指定新字符集。默认状况下,这个属性的值为"UTF-16",但能够经过元素、响应头部或直接设置 charset 属性修改这个值
alert(document.charset); //"UTF-16" document.charset = "UTF-8";
defaultCharset属性:表示根据默认浏览器及操做系统的设置,当前文档默认的字符集应该是什么。若是文档没有使用默认的字符集,那 charset 和 defaultCharset 属性的值可能会不同
if (document.charset != document.defaultCharset){ alert("Custom character set being used."); }
自定义数据属性
HTML5 规定能够为元素添加非标准的属性,但要添加前缀 data-,这些属性能够任意添加、随便命名,只要以 data-开头便可
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
添加了自定义属性以后,能够经过元素的 dataset 属性来访问自定义属性的值。dataset 属性的值是 DOMStringMap 的一个实例,也就是一个名值对儿的映射。在这个映射中,每一个 data-name 形式
的属性都会有一个对应的属性,只不过属性名没有 data-前缀(好比,自定义属性是 data-myname,
那映射中对应的属性就是 myname)
//本例中使用的方法仅用于演示 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); }
插入标记
innerHTML 属性
在读模式下,innerHTML 属性返回与调用元素的全部子节点(包括元素、注释和文本节点)对应的 HTML 标记;
<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>元素来讲,它的 innerHTML 属性会返回以下字符串 <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>
在写模式下,innerHTML 会根据指定的值建立新的 DOM 树,而后用这个 DOM 树彻底替换调用元素原先的全部子节点
div.innerHTML = "Hello world!"; div.innerHTML = "Hello & welcome, <b>\"reader\"!</b>"; //结果: //<div id="content">Hello & welcome, <b>"reader"!</b></div>
不一样浏览器返回的文本格式会有所不一样。IE 和 Opera 会将全部标签转换为大写形式,而 Safari、Chrome 和 Firefox 则会原本来本地按照原先文档中(或指定这些标签时)的格式返回 HTML,包空格和缩进
在大多数浏览器中,经过 innerHTML 插入<script>
元素并不会执行其中的脚本
div.innerHTML = "<script defer>alert('hi');<\/script>"; //无效 //下面这几行代码均可以正常执行 div.innerHTML="_<script defer>alert('hi');<\/script>"; div.innerHTML="<div> </div><script defer>alert('hi');<\/script>"; div.innerHTML="<input type=\"hidden\"><script defer>alert('hi')<\/script>";
大多数浏览器都支持以直观的方式经过 innerHTML 插入<style>
元素
div.innerHTML="<style type=\"text/css\">body{background-color:red;</style>" //IE8 及更早版本中 div.innerHTML="_<style type=\"text/css\">body{background-color:red;</style>" div.removeChild(div.firstChild);
并非全部元素都支持 innerHTML 属性。不支持 innerHTML 的元素有:
<col>、<colgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>和<tr>
不管何时,只要使用 innerHTML 从外部插入 HTML,都应该首先以可靠的方式处理 HTML。IE8 为此提供了 window.toStaticHTML()方法,这个方法接收一个参数,即一个 HTML 字符串;返回一个通过无害处理后的版本——从源 HTML 中删除全部脚本节点和事件处理程序属性
var text = "<a href=\"#\" onclick=\"alert('hi')\">Click Me</a>"; var sanitized = window.toStaticHTML(text); //Internet Explorer 8 only alert(sanitized); //"<a href=\"#\">Click Me</a>"
outerHTML 属性
在读模式下,outerHTML 返回调用它的元素及全部子节点的 HTML 标签
<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 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>
在写模式下,outerHTML会根据指定的 HTML 字符串建立新的 DOM 子树,而后用这个 DOM 子树彻底替换调用元素。
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);
insertAdjacentHTML()方法:它接收两个参数,插入位置和要插入的 HTML 文本
第一个参数必须是下列值之一(这些值都必须是小写形式):
"beforebegin",在当前元素以前插入一个紧邻的同辈元素; "afterbegin",在当前元素之下插入一个新的子元素或在第一个子元素以前再插入新的子元素; "beforeend",在当前元素之下插入一个新的子元素或在最后一个子元素以后再插入新的子元素; "afterend",在当前元素以后插入一个紧邻的同辈元素。
第二个参数是一个 HTML 字符串(与 innerHTML 和 outerHTML的值相同),若是浏览器没法解析该字符串,就会抛出错误
//做为前一个同辈元素插入 element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>"); //做为第一个子元素插入 element.insertAdjacentHTML("afterbegin", "<p>Hello world!</p>"); //做为最后一个子元素插入 element.insertAdjacentHTML("beforeend", "<p>Hello world!</p>"); //做为后一个同辈元素插入 element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
内存与性能问题
在使用 innerHTML、outerHTML 属性和 insertAdjacentHTML()方法时,最好先手工删除要被替换的元素的全部事件处理程序和 JavaScript 对象属性
建立和销毁 HTML 解析器也会带来性能损失,因此最好可以将设置 innerHTML或 outerHTML 的次数控制在合理的范围内
var itemsHtml = ""; for (var i=0, len=values.length; i < len; i++){ itemsHtml += "<li>" + values[i] + "</li>"; } ul.innerHTML = itemsHtml;
scrollIntoView()方法
//让元素可见 document.forms[0].scrollIntoView();
文档模式
文档模式决定了你可使用哪一个级别的 CSS,能够在 JavaScript 中使用哪些 API,以及如何对待文档类型(doctype)
要强制浏览器以某种模式渲染页面,可使用 HTTP 头部信息X-UA-Compatible,或经过等价的标签来设置
<meta http-equiv="X-UA-Compatible" content="IE=IEVersion">
默认状况下,浏览器会经过文档类型声明来肯定是使用最佳的可用文档模式,仍是使用混杂模式,经过 document.documentMode 属性能够知道给定页面使用的是什么文档模式
var mode = document.documentMode;
children属性
因为 IE9 以前的版本与其余浏览器在处理文本节点中的空白符时有差别,所以就出现了 children属性
这个属性是 HTMLCollection 的实例,只包含元素中一样仍是元素的子节点
除此以外,children 属性与 childNodes 没有什么区别,即在元素只包含元素子节点时,这两个属性的值相同
var childCount = element.children.length; var firstChild = element.children[0];
contains()方法
调用 contains()方法的应该是祖先节点,也就是搜索开始的节点,这个方法接收一个参数,即要检测的后代节点。若是被检测的节点是后代节点,该方法返回 true;不然,返回 false
alert(document.documentElement.contains(document.body)); //true
compareDocumentPosition()也可以肯定节点间的关系,这个方法用于肯定两个节点间的关系,返回一个表示该关系的位掩码( bitmask)
var result = document.documentElement.compareDocumentPosition(document.body); alert(!!(result & 16)); //16表明节点被包含(给定的节点是参考节点的后代)
兼容性写法
function contains(refNode, otherNode){ if (typeof refNode.contains == "function" && (!client.engine.webkit || client.engine.webkit >= 522)){ return refNode.contains(otherNode); } else if (typeof refNode.compareDocumentPosition == "function"){ return !!(refNode.compareDocumentPosition(otherNode) & 16); } else { var node = otherNode.parentNode; do { if (node === refNode){ return true; } else { node = node.parentNode; } } while (node !== null); return false; } }
innerText 属性:能够操做元素中包含的全部文本内容,包括子文档树中的文本
在经过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> 对于这个例子中的<div>元素而言,其 innerText 属性会返回下列字符串: This is a paragraph with a list following it. Item 1 Item 2 Item 3
在经过innerText 写入值时,结果会删除元素的全部子节点,插入包含相应文本值的文本节点;也对文本中存在的 HTML 语法字符(小于号、大于号、引号及和号)进行了编码
div.innerText = "Hello & welcome, <b>\"reader\"!</b>"; 运行以上代码以后,会获得以下所示的结果 <div id="content"> Hello &welcome,<b>"reader"!</b> </div>
设置 innerText 永远只会生成当前节点的一个子文本节点,而为了确保只生成一个子文本节点,就必需要对文本进行 HTML 编码。利用这一点,能够经过 innerText 属性过滤掉 HTML 标签。方法是将 innerText 设置为等于 innerText,这样就能够去掉全部 HTML 标签
div.innerText = div.innerText;
因为不一样浏览器处理空白符的方式不一样,所以输出的文本可能会也可能不会包含原始 HTML 代码中的缩进
兼容性:
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; } } setInnerText(div, "Hello world!"); alert(getInnerText(div)); //"Hello world!"
outerText 属性
在读取文本值时,outerText 与 innerText 的结果彻底同样。但在写模式下,outerText 就彻底不
同了:outerText 不仅是替换调用它的元素的子节点,而是会替换整个元素(包括子节点)
div.outerText = "Hello world!"; //这行代码实际上至关于以下两行代码: var text = document.createTextNode("Hello world!"); div.parentNode.replaceChild(text, div);
本质上,新的文本节点会彻底取代调用 outerText 的元素。此后,该元素就从文档中被删除,没法访问
滚动
scrollIntoView()和 scrollIntoViewIfNeeded()的做用对象是元素的容器,而 scrollByLines()和scrollByPages()影响的则是元素自身
//将页面主体滚动 5 行 document.body.scrollByLines(5); //在当前元素不可见的时候,让它进入浏览器的视口 document.images[0].scrollIntoViewIfNeeded(); //将页面主体往回滚动 1 页 document.body.scrollByPages(-1); 因为 scrollIntoView()是惟一一个全部浏览器都支持的方法,所以仍是这个方法最经常使用。