题目地址: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之间直播答疑。
有兴趣参与的能够多多关注下,免费的。
以上~