2

我试图: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

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

null

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

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

我的问题是:

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

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

编辑:我发现与 JQuery 选择类似的问题:document.ready() 上的目标

4

2 回答 2

2

这是基于 WebKit 和 Blink 的浏览器的一个已知问题,从未直接解决。web-platform-tests 建议的解决方法是请求一个动画帧,这仅在页面渲染后发生,此时: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
于 2021-04-17T11:29:22.310 回答
1

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

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

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

这将适用于所有浏览器。

于 2021-04-15T09:09:32.930 回答