JS學習10(DOM擴展)

選擇符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一樣,寫時覆蓋調用節點。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,924評論 18 139
  • Class 學過Java的小伙伴會發現, 這個class和Java里的class基本語法并沒有什么區別... 下面...
    劉翾閱讀 992評論 2 2
  • 月底的時候,由于店里員工越來越多,原先的宿舍已經無法容納更多的人了,于是我們被迫換宿舍。 聽到這個消息的時候,我正...
    素墨wz閱讀 241評論 0 0