Node.contains()无法将孙子元素识别为真值的问题咨询
Node.contains()返回false的异常问题 嘿,你的DOM结构和代码逻辑本身是没问题的,但在Chrome 63里出现contains()返回false的情况,大概率是下面几个原因之一,我帮你逐一排查:
元素已脱离当前DOM树
有时候页面的动态操作(比如框架重新渲染、JS把元素移到其他容器)会导致你获取的grandparent和grandchild不在同一棵DOM树上。举个例子:如果在你获取这两个元素之后,有代码把.grand-child从原父容器里移走了,或者.grand-parent被重新渲染替换了,那它们的层级关联就断了。你可以在console.log前加两行验证:console.log(document.body.contains(grandparent)); console.log(document.body.contains(grandchild));如果其中一个返回false,就说明这个元素已经不在当前页面的DOM结构里了。
代码执行时机过早
你是不是没等DOM完全加载就执行了这段代码?比如把JS写在<head>标签里,没有监听DOMContentLoaded事件,这时候.grand-child或.grand-parent可能还没被渲染到页面上(异步渲染的组件也可能出现这个问题)。你可以把代码放在DOM加载完成的回调里试试:document.addEventListener('DOMContentLoaded', function() { const grandchild = document.querySelector(".grand-child"); const grandparent = document.querySelector(".grand-parent"); console.log(grandparent.contains(grandchild)); });Chrome 63的版本特定bug
Chrome 63是2017年底的旧版本,当时确实存在一些DOM API的小问题,比如元素克隆后contains判断异常、Shadow DOM相关的兼容问题。如果上面两种情况都排除了,你可以用closest方法反向验证:console.log(grandchild.closest('.grand-parent') === grandparent);如果这个返回true,那基本可以确定是旧版本Chrome的
contains方法bug,直接用closest作为替代方案就好。
另外,你也可以直接在Chrome控制台里手动获取这两个元素,再执行grandparent.contains(grandchild),这样能快速排除代码执行顺序的问题。
内容的提问来源于stack exchange,提问作者Stanley Nguyen

