Node.contains 函数兼容处理

时间:2021-04-05 00:47:29

​生活不止眼前的苟且,还有诗和远方​

掘友们,大家好我是前端奶爸,入行5年的前端小学生????~
工作八小时摸鱼四小时,喜欢跑步但不是为了让自己更瘦,而是为了让自己活得更久~
活到九十九,卷到九十九~

前言

好久不写文章了,而且这是我在51的第一篇文章,都不知道跟大家怎么打招呼了,新的一年开始,也应该收心,做一些文字的记录以及分享了。

先说下写这篇文章的由来吧,接到一个需求需要在项目中实现一个效果,就是点击其他区域隐藏dom的操作,试了很多的方式,感觉都不是特别合理,所以针对当前需求做了一个方法的实现,使用​​dom​​​原生方法 ​​contains​​进行判断当前点击的元素是否是指定父级的子级,然后进行判断是否隐藏指定元素。

具体业务逻辑方法就不在这里赘述了,主要讲下​​contains​​方法。

contains方法

​Node​​​ 接口的 ​contains()​​  方法返回一个布尔值,表示一个节点是否是给定节点的后代,即该节点本身、其直接子节点(​​childNodes​​)、子节点的直接子节点等。

​参数​

  • ​otherNode​​​要测试的​​节点​​​。
    备注:  ​​otherNode​​​ 不是可选的,但是可以设置为 ​​null​​。

​返回值​

返回一个布尔值,如果 ​​otherNode​​​ 包含在节点中会返回 ​​true​​​,否则返回 ​​false​​。

如果 ​​otherNode​​​ 参数为 ​​null​​​,则 ​​contains()​​​ 始终返回 ​​false​​。

​示例​

下面的函数用来检查一个元素是否是 body 元素的后代元素。由于 ​​contains​​​ 会包含元素自身,而确定 body 是否包含自身不是设计 ​​isInPage​​​ 的意图,这种情况明确返回 ​​false​​。

function isInPage(node) {
return (node === document.body) ? false : document.body.contains(node);
}

​规范​

Specification

​DOM Standard # ref-for-dom-node-contains①​

​浏览器兼容性​

​Report problems with this compatibility data on GitHub​


desktop

mobile











Chrome

Edge

Firefox

Opera

Safari

Chrome Android

Firefox for Android

Opera Android

Safari on iOS

Samsung Internet

WebView Android

​contains​

16Toggle history

12Toggle history

9Toggle history

7Toggle history

1.1Toggle history

18Toggle history

9Toggle history

10.1Toggle history

1Toggle history

1.0Toggle history

4.4Toggle history

兼容处理

因为是原生方法,兼容性有限,所以针对公司的项目兼容需求,还需要进行兼容处理。具体代码如下:

const contains = (root, el) => {
if (root.compareDocumentPosition) return root === el || !!(root.compareDocumentPosition(el) & 16);
if (root.contains && el.nodeType === 1) {
return root.contains(el) && root !== el;
}
while ((el = el.parentNode)) if (el === root) return true;
return false;
};

这段代码实现了一个检测节点是否存在于指定容器中的函数​​contains​​,其中使用了三种不同的方式进行判断:

  1. 如果浏览器支持​​compareDocumentPosition​​​方法,则直接使用该方法进行判断。首先判断​​root​​​节点是否等于​​el​​​节点,如果是,则返回​​true​​​;否则,使用​​compareDocumentPosition​​​方法判断​​el​​​节点是否在​​root​​​节点中,如果结果为16,则返回​​true​​​,否则返回​​false​​。
  2. 如果浏览器不支持​​compareDocumentPosition​​​方法,但支持​​contains​​​方法,则判断​​el​​​节点是否是一个元素节点(nodeType为1),如果是,则使用​​contains​​​方法判断​​el​​​节点是否在​​root​​​节点中,并且​​root​​​节点不等于​​el​​​节点,如果满足,则返回​​true​​​,否则返回​​false​​。
  3. 如果浏览器既不支持​​compareDocumentPosition​​​方法,也不支持​​contains​​​方法,则使用​​while​​​循环遍历​​el​​​节点的所有祖先节点,判断是否有节点等于​​root​​​节点,如果有,则返回​​true​​​,否则返回​​false​​。

综合三种方式,可以实现在各种浏览器中兼容检测节点是否存在于指定容器中的功能。

总结

方法整体的实现难度不是很大,就是针对当前原生方法的不支持的内容进行补充,如果有用到或者有幸刷到奶爸文章的同学,动动发财的小手点个赞~~

疫情已结束,春暖花开,JYM,开始搞钱~~~