這是我參與8月更文挑戰的第10天,活動詳情查看:8月更文挑戰。javascript
關於【SSD系列】:
前端一些有意思的內容,旨在3-10分鐘裏, 500-1500字,有所獲,又不爲所累。css
先提問一波:(無框架前提下)html
經常使用查詢節點方法有哪些前端
什麼是空白節點??她又究竟是個什麼東西vue
querySelectorAll 有哪些坑java
怎麼查詢僞元素node
四種刪除節點方式你都知道嗎react
HTMLCollection 和 NodeList的區別jquery
怎樣刪除全部的孩子節點git
咱們已經先jquery, vue, react等前端框架帶來的便利了:
$
走天下,無限連。ref
就能拿到對應節點。離開了這些框架,你還能666的操做Node節點嗎?
先放一段測試的html代碼
<div class="outer" id="outer">
<ul class="list list-1">
<li class="item">list-one</li>
<li class="item">list-two</li>
<li class="item">list-three</li>
</ul>
</div>
<input type="button" name="btnSubmit" value="刷新"/>
複製代碼
根據元素的id
屬性值進行節點查詢,返回單一節點。
document.getElementById("outer") // <div class="outer" id="outer">......
複製代碼
getElementsByClassName
根據元素的classname屬性值就行查詢。
document.getElementsByClassName("item") // HTMLCollection(3) [li.item, li.item, li.item]
複製代碼
getElementsByName
根源節點的name屬性進行查詢。
document.getElementsByName("btnSubmit") // NodeList [input]
複製代碼
getElementsByTagName
根據節點標籤名進行查詢。
document.getElementsByTagName("li") // HTMLCollection(3) [li.item, li.item, li.item]
複製代碼
querySelector
根絕css選擇器進行節點查詢,返回單個節點。
document.querySelector("#outer") // <div class="outer" id="outer">......
複製代碼
querySelectorAll
根絕css選擇器進行節點查詢,返回節點列表。
document.querySelectorAll(".item") // NodeList(3) [li.item, li.item, li.item]
複製代碼
在沒有querySelector
和querySelectorAll
出現以前,基本都是經過前四個查詢方法配合 childNodes
和parentNode
方法擴展出各類方法。
object
標籤元素,之前主要用於flash,pdf等等其返回的靜態的NodeList
, 隨後對DOM
元素的改動不會影響其集合的內容。
下面的代碼能夠看到,添加一個節後後, nodeList長度並無變化。
<ul class="list list-1">
<li class="item">list-one</li>
<li class="item">list-two</li>
<li class="item">list-three</li>
</ul>
<script> var nodeList = document.querySelectorAll(".item"); console.log("len:", nodeList.length); // 3 var liEl = document.createElement("li"); liEl.className = "item"; liEl.innerHTML = "list-for" document.querySelector(".list").appendChild(liEl); console.log("len:", nodeList.length); //3 </script>
複製代碼
querySelectorAll可能返回的不是你指望的值
<div class="outer">
<div class="select">
<div class="inner">
</div>
</div>
</div>
<script> var select = document.querySelector('.select'); var inner = select.querySelectorAll('.outer .inner'); inner.length; // 1, not 0! </script>
複製代碼
那麼怎樣才能返回指望的結果呢?答案是 :scope
var select = document.querySelector('.select');
var inner = select.querySelectorAll(':scope .outer .inner');
inner.length; // 0
複製代碼
<div id="foo\bar"></div>
<div id="foo:bar"></div>
<script> console.log('#foo\bar') // "#fooar" document.querySelector('#foo\bar') // 不匹配任何元素 console.log('#foo\\bar') // "#foo\bar" console.log('#foo\\\\bar') // "#foo\\bar" document.querySelector('#foo\\\\bar') // 匹配第一個div document.querySelector('#foo:bar') // 不匹配任何元素 document.querySelector('#foo\\:bar') // 匹配第二個div </script>
複製代碼
細心的通知可能發現了,上面的方法,有的返回的是HTMLCollection,有的返回的是NodeList。 他們有什麼區別呢?
這裏先要弄清晰繼承關係:
HTMLElement -> Element -> Node-> EventTarget
複製代碼
EventTarget 前一個提供了事件分發能力,自己也是一個訂閱發佈中心,更多詳情參見 3行代碼一個訂閱發佈中心,不會不知道吧。
Node 有 12種節點類型,詳情參見 NodeType,咱們經常使用的 div, span等等屬於nodeType=1的節點類型。
因此:
HTMLCollection 是元素節點類型,即nodeType爲1的節點。
NodeList 是節點集合,包含文本節點,註釋節點等等其餘節點。
// html代碼
<style> .nihao::before{ content: '你好,'; } </style>
<div class="nihao" id="nihao">
Tom
</div>
複製代碼
答案是不能,但你能夠經過 window.getComputedStyle 來獲取其樣式。
window.getComputedStyle(nihao, "before")["content"] // "\"你好,\""
複製代碼
先特出測試的html代碼段
<ul class="list list-1">
<li class="item">list-one</li>
<li class="item">list-two</li>
<li class="item">list-three</li>
</ul>
複製代碼
這種咱們用的最多的方法,前提是首先得得到要被刪除元素的父節點,可使用parentNode
或者parentElement
得到。
var ul = document.querySelector(".list");
console.log("li length", ul.children.length); // 3
ul.removeChild(ul.children[0]) // removeChild
console.log("li length", ul.children.length); // 2
複製代碼
這個方法屬於 Element對象上,也就代表,其餘nodeType類型是不可使用的, 其不須要得到副節點。
var ul = document.querySelector(".list");
console.log("li length", ul.children.length); // 3
ul.children[0].remove(); // remove
console.log("li length", ul.children.length); // 2
複製代碼
var ul = document.querySelector(".list");
console.log("li length", ul.children.length); // 3
ul.children[0].outerHTML = null // outerHTML
console.log("li length", ul.children.length); // 2
複製代碼
從其餘的document文檔中獲取一個節點。 該節點以及它的子樹上的全部節點都會從原文檔刪除。
var ul = document.querySelector(".list");
console.log("li length", ul.children.length); // 3
document.adoptNode(ul.children[0]); // adoptNode
console.log("li length", ul.children.length); // 2
複製代碼
批量刪除,好比清除某個節點下的全部子節點,通常是使用while
循環,暴力的方式是 innerHTML = null
。
innerHTML = null
可能致使事件監聽器沒有被取消,以致使內存泄漏,具體有麼有,還得看瀏覽器的實現。
咱們封裝一個吧:
function clearChildNodes(node){
while(node.hasChildNodes()){
node.removeChild(node.firstChild);
}
}
const ul = document.querySelector(".list");
console.log("nodes:", ul.childNodes.length); // 7
clearChildNodes(ul);
console.log("nodes:", ul.childNodes.length); // 0
複製代碼
爲何是7個節點呢? 看圖上的空白節點,有4個, 4+3 =7樓。
咱們調整一下代碼, 刪除空白,再看輸出
<ul class="list list-1"><li class="item">list-one</li><li class="item">list-two</li><li class="item">list-three</li></ul>
複製代碼
那空白節點,到底是個什麼東西??
看代碼,其實就是nodeType爲3的文本節點。進行輸出的時候其textConent爲空。
var ul = document.querySelector(".list");
console.log("li length", ul.childNodes.length); // 7
var firstNode = ul.childNodes[0];
console.log("nodeType", firstNode.nodeType); // 3
console.log("content", firstNode.textContent); //
複製代碼
咱們不妨添加一點內容, 你就能清晰的知道了, 其childNodes長度依舊是7,第一個文本節點的內容是 text content
<ul class="list list-1">text content
<li class="item">list-one</li>
<li class="item">list-two</li>
<li class="item">list-three</li>
</ul>
複製代碼
是否是很簡單,一切都看起來沒那麼難,這樣,你才容易入坑啊。
篇幅優先,若是star超過 100, 再寫一篇節點增長和更新的文章。
寫做不易,你的一讚一評就是我前行的最大動力。
技術交流羣,請加微信 dirge-cloud。