題目地址:github.com/zhangxinxu/…html
題目內容以下(點擊查看大圖):html5
本題主要考察如何判斷DOM節點文檔先後位置,父子關係等。我看了下最後的回答,近9成的回答使用了很是囉嗦的方法,比例之高,實在出乎意料。實際上,本題有很是簡單、寥寥數行就能實現的方法,只要你知道下面這兩個頗有用的DOM原生API,一個是contains()
方法,判斷DOM元素或節點是否有包含關係;另一個是compareDocumentPosition()
方法,更強悍的DOM或節點位置關係判斷,不管是先後、內外仍是跨文檔均可以。node
本次B站答疑直播在週六上午10:34分開始,持續約30分鐘,有錄播,能夠點擊這裏觀看,建議1.5倍速食用。git
contains()
方法是一個很古老的API,用來判斷兩個DOM節點之間的包含關係,語法以下:github
node.contains(otherNode)複製代碼
返回布爾值,表示node
是否包含otherNode
,或者就是node
自己。瀏覽器
例如:bash
document.documentElement.contains(document.body); // 返回值是true
document.body.contains(document.body); // 返回值是true
document.body.contains(document.documentElement); // 返回值是false複製代碼
此API兼容性良好,IE5就開始支持了,使用很是方便,咱們無需專門遍歷祖先元素用判斷兩個節點之間的嵌套關係。app
若是判斷的兩個節點元素是跨iframe文檔的,則會被認爲是false
。例如咱們直接藉助Blob動態建立一個非外鏈iframe,代碼以下:ide
var htmlIframe = '<img id="img" src="https://.../mm.jpg" onclick="console.log(window.parent.document.body.contains(this))">';
var iframe = document.createElement('iframe');
var blob = new Blob([htmlIframe], { 'type': 'text/html'});
iframe.src = URL.createObjectURL(blob);
iframeBlob1.appendChild(iframe);複製代碼
點擊圖片,能夠看到控制檯輸出結果以下:wordpress
若是想要知道iframe內外的包含關係,則須要使用另外的API:compareDocumentPosition()
。
本題中圖片DOM元素先後位置的比對徹底不須要寫循環進行遍歷,有現成的API能夠實現咱們想要的效果,那就是Node.compareDocumentPosition
API。
此API很有深度,我專門寫了篇文章介紹這個API,可參見這裏:「深刻Node.compareDocumentPosition API」。
例如:
var compareValue = img.compareDocumentPosition(compareImg);
if (compareValue == 2) {
// compareImg在前
} else if (compareValue == 4) {
// compareImg在後
} else if (compareValue == 0) {
// 就是compareImg元素自身
} else {
// 其它位置關係
}複製代碼
若是compareValue
是2
,則表示compareImg
在img
的前面;若是是4
,則表示compareImg
在img
的後面。
由此咱們能夠輕鬆判斷點擊圖片和對比圖片之間的文檔位置關係,寥寥幾行代碼的事情。
不過須要注意的是,若是是判斷其餘非替換元素的位置關係,則不能使用數值比對,由於可能compareDocumentPosition()
方法執行後的值是一個混合數值,例如:
// 返回值是 10,8 + 2
document.body.compareDocumentPosition(document.documentElement);
// 返回值是 20,16 + 4
document.documentElement.compareDocumentPosition(document.body)複製代碼
咱們須要使用單個&
符合和對應目標值進行與位運算的結果來斷定,例如:
if (document.body.compareDocumentPosition(document.documentElement) & 2) {
// document.documentElement在document.body前面
// ...
}複製代碼
若是不是很理解,能夠訪問我剛寫的專門深刻介紹compareDocumentPosition的文章。
例如:
container.onclick = function (event) {
// event.target ...
}複製代碼
業界用的比較多的方法是使用tagName值進行判斷,以下:
event.target.tagName == 'IMG' // true或false複製代碼
全部瀏覽器都返回大寫標籤名,固然,若是你不放心(之後變了,或者遇到SB瀏覽器),能夠更嚴格比對下:
/^img$/i.test(event.target.tagName) // true或false複製代碼
event.target.tagName.toLowerCase() == 'img' // true或false複製代碼
咱們還能夠使用nodeName進行判斷,例如:
event.target.nodeName == 'IMG' // true或false複製代碼
最後,在介紹一種對象類型判斷方法,以下:
event.target instanceof Image // true或false複製代碼
也是能夠的。
Node.contains()
方法;event.target.tagName/nodeName == 'IMG'複製代碼
/^img$/i.test(event.target.tagName)複製代碼
event.target.tagName.toLowerCase() == 'img'複製代碼
event.target instanceof Image複製代碼
Node.compareDocumentPosition()
。關於直播答疑
每週三會在這個項目的issues中發佈小測題,依次CSS,JS和DOM,每週六上午10:00~11:00之間直播答疑。
有興趣參與的能夠多多關注下,免費的。
以上~