"DOM2 級遍歷和範圍"模塊定義了兩個方法用於輔助完成順序遍歷 DOM 結構的類型: NodeIterator 和 TreeWalker 。這兩個類型可以基於給定的起點對 DOM 結構執行深度優先(depth-first)的遍歷操做。javascript
任何節點均可以做爲遍歷的根節點。引用《JavaScript高級程序設計(第3版)》的插圖,表示以 document 對象爲根節點:
html
使用document.createNodeIterator(rootNode, whatToShow, filter, isEntrityReferenceExpansion?)
方法能夠建立 NodeIterator 的實例。 4 個參數的意思:
java
// node 爲每次遍歷的節點對象
function acceptNode(node) {
// 過濾除了 div 之外的元素
return node.nodeName.toLowerCase() === 'div'
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP
}複製代碼
函數createNodeIterator()
執行後,返回一個 NodeIterator 的實例,該對象主要有兩個方法:node
null
。null
。完整實例以下:函數
<body> <div class="div1">div1</div> <div class="div2"> <p>pppppp</p> text </div> </body>複製代碼
// 過濾的類型選擇
let whatToShow = NodeFilter.SHOW_ALL;
// 過濾器(傳入函數)
let filter = function (node) {
return node.nodeName.toLowerCase() === 'div' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
}
// 過濾器2(傳入對象)
let filter2 = {
acceptNode: filter
}
// 建立迭代器
let iterator = document.createNodeIterator(document.body, whatToShow, filter, false);
// 測試
console.log(iterator.nextNode()); // "<div class="div1">div1</div>"
console.log(iterator.previousNode()); // "<div class="div2">...</div>"
console.log(iterator.nextNode()); // "<div class="div1">div1</div>"
console.log(iterator.nextNode()); // null
複製代碼
使用document.createTreeWalker()
方法能夠建立 TreeWalker 對象,參數與createNodeIterator()
方法一致。TreeWalker 是 NodeIterator 的一個高級版本,使用方法也基本一致,有一點除外,過濾函數的返回值若是是 "NodeFilter.FILTER_REJECT" ,該節點的子節點都會被跳過。除了包含 nextNode() 和 previousNode() 方法以外,還提供了以下屬性/方法:
測試
<body> <div id="div1"> div1 <div id="div1_1"> div1.1</div> <div id="div1_2"> div1.2</div> </div> <div id="div2"> div2 <p> div2-p</p> </div> </body>複製代碼
let filter = function (node) {
return node.nodeName.toLowerCase() === 'div' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
}
let walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, filter, false)
// 測試
console.log(walker.nextNode()); // "<div id="div1">...</div>"
console.log(walker.nextSibling()); // "<div id="div2">...</div>"
console.log(walker.previousSibling()); // "<div id="div1">...</div>"
console.log(walker.firstChild()); // "<div id="div1_1">...</div>"
console.log(walker.parentNode()); // "<div id="div1">...</div>"
console.log(walker.lastChild()); // "<div id="div1_2">...</div>"
console.log(walker.nextNode()); // "<div id="div2">...</div>"複製代碼
須要注意的是,"walker" 只能在 TreeWalker 對象內"遊走",上面幾個方法也是針對已過濾的結果的相對位置"遊走",即便"div"內有"Text"類型的節點。除非建立 TreeWalker 對象的第一第二個參數分別傳入 document 和 null ,就能夠在 DOM 樹內隨意"遊走"。
ui
"DOM2 級遍歷和範圍"模塊定義"範圍"(range)接口。經過範圍能夠選擇文檔中的一個區域,而沒必要考慮節點的界限。使用document.createRange()
方法能夠建立 range 對象。
spa
Range 對象的屬性提供了當前範圍在文檔中的位置信息。
設計
<p>hello</p>
中被選擇了"llo",本屬性值爲 3 ;不然,表示起點節點在父節點的 childNodes 是第幾個,即經過range.startContainer.childNodes[range.startOffset - 1]
可訪問起點節點。如下方法均用於修改 Range 對象的範圍,無返回值。
code
<p>hello</p>
選擇了"llo</p>"時,會自動將其補全,即起點節點爲<p>llo</p>
。能夠當作快速設置指定屬性。使用如下方法,能夠對 DOM 刪除或插入。
<p>hello</p>
被刪除了"llo</p>",則剩下的節點會變成<p>he</p>
,仍是完整的節點。<div>hello <b>world</b></div>
的 HTML 文檔片斷,範圍選擇"llo <b>world</b>
",使用document.createElement('p')
建立一個用於環繞的 node 節點對象,而後使用本方法,原 HTML 文檔片斷將變爲<div>he<p>llo <b>world</b></p></div>
。須要注意的是,在使用本方法前,對 "node" 對象插入其餘節點是不會有效果的;但爲 "node" 對象添加特性是有效果的。本方法執行時,後臺會執行以下步驟:<p id="p1">p1</p><p id="p2">p2</p>
,分別獲取"p1"、"p2"節點對象,建立range對象設定起點終點range.setStartAfter(p1); range.setEndBefore(p2)
,由於"p1"和"p2"是相鄰節點,因此range.collapsed
的值爲true
。 cloneContents()
方法區分。deleteContents()
方法仍然會刪除 DOM。)