JavaScript querySelector and CSS :target pseudo-class



我正在尝试在文档加载后获取带有伪类:target的目标元素。 我创建了以下示例来说明问题。

<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener("DOMContentLoaded",function(){
console.log(document.querySelector(":target"));
});
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>

如果我加载test.html,则控制台输出:

null

如果我在 Chrome 和 Opera 上加载test.html#test,则控制台输出:

null

如果我在火狐和IE11上加载test.html#test,那么控制台输出:

<div id="test"></div>

我的问题是:

  1. 哪些浏览器具有正确的行为?
  2. DOMContentLoaded是调用querySelector(":target")的正确事件吗?
  3. 有没有另一种方法可以在文档加载后获取目标元素?

PS :多亏了setTimeout,我成功地解决了Chrome和Opera上的问题,但这不是一个很好的解决方案。有人有更好的主意吗?

编辑:我在 document.ready() 上发现 JQuery 选择 :target 时遇到了类似的问题

这是基于 WebKit 和 Blink 的浏览器的已知问题,从未直接解决过。Web 平台测试建议的解决方法是请求动画帧,这仅在页面渲染后发生,此时:target伪似乎成功匹配:

async_test(function() {
var frame = document.createElement("iframe");
var self = this;
frame.onload = function() {
// :target doesn't work before a page rendering on some browsers.  We run
// tests after an animation frame because it may be later than the first
// page rendering.
requestAnimationFrame(self.step_func_done(init.bind(self, frame)));
};
frame.src = "ParentNode-querySelector-All-content.xht#target";
document.body.appendChild(frame);
})

我的测试表明,简单地使用onload就可以了,但是作者可能会做一些事情,此外,一次调用requestAnimationFrame()几乎不需要任何费用,所以你不妨效仿。

以下测试使用onload(与DOMContentLoaded相反,后者在构建 DOM 树后立即触发,但不一定渲染):

data:text/html,<!DOCTYPE html><script>window.onload=function(){console.log(document.querySelector(":target"));};</script><div id="test"></div>#test

以下测试将requestAnimationFrame()onload结合使用:

data:text/html,<!DOCTYPE html><script>window.onload=requestAnimationFrame(function(){console.log(document.querySelector(":target"));});</script><div id="test"></div>#test

看起来Firefox具有理想的行为,尽管可能不是正确的行为。

不过,作为替代方案,您可以使用:

document.addEventListener('DOMContentLoaded', () => document.querySelector(window.location.hash));

这将适用于所有浏览器。

最新更新