JavaScript querySelector 和 CSS :target 伪类
Posted
技术标签:
【中文标题】JavaScript querySelector 和 CSS :target 伪类【英文标题】:JavaScript querySelector and CSS :target pseudo-class 【发布时间】:2021-07-10 07:17:33 【问题描述】:我正在尝试在文档加载后使用伪类: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
如果我在 Firefox 和 IE11 上加载 test.html#test
,那么控制台输出:
<div id="test"></div>
我的问题是:
-
哪些浏览器的行为正确?
DOMContentLoaded
是调用querySelector(":target")
的正确事件吗?
是否有其他方法可以在文档加载后获取目标元素?
PS:感谢setTimeout
,我成功解决了 Chrome 和 Opera 上的问题,但这不是一个好的解决方案。有人有更好的主意吗?
编辑:我发现与 JQuery Selecting :target on document.ready() 类似的问题
【问题讨论】:
来自Selectors API Level 1: "建议作者虽然允许在选择器中使用 伪元素,但它们不会匹配文档中的任何元素,因此会不会导致返回任何元素。因此,建议作者避免在传递给本规范中定义的方法的选择器中使用伪元素。" 但:target
是pseudo class 而不是pseudo element
在onload
中,它在 Chrome 中可以使用 fine for me,但在 Safari 中则不行...一个破解方法是在 :target
上设置一个小的过渡(0.01 秒)并收听过渡结束事件。
【参考方案1】:
这是一个known issue,带有基于 WebKit 和 Blink 的浏览器,从未被直接解决。 web-platform-tests 建议的解决方法是request an animation frame,它只发生在页面渲染之后,此时: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
【讨论】:
关于第一段,似乎有必要在onload
中调用requestAnimationFrame,至少对于Chrome来说,当然是因为crbug.com/1018120【参考方案2】:
看起来 Firefox 具有理想的行为,但可能不是正确的。
不过,作为替代方案,您可以使用:
document.addEventListener('DOMContentLoaded', () => document.querySelector(window.location.hash));
这将适用于所有浏览器。
【讨论】:
“看起来 Firefox 具有理想的行为...” - 违反规范如何是“理想行为”? @Andreas - 规范既不是万无一失的也不是一成不变的。 如果我加载带有空 location.hash 的文档,我会收到错误Uncaught DOMException
。这意味着我需要在querySelector
之前添加一个检查,但它是:target
的一个很好的替代品。
回复:“也就是说我需要在querySelector
之前添加一个检查”。正确的。您可以直接写如下内容:if (window.location.hash !== '') console.log(document.querySelector(window.location.hash)); else console.log('The current URL contains no hashfragment.');
.
这个 will 不会捕获 github.com/WICG/scroll-to-text-fragment(Chrome 中已经存在),因为 :target
匹配文本片段的父元素,但 location.hash
不是设置。以上是关于JavaScript querySelector 和 CSS :target 伪类的主要内容,如果未能解决你的问题,请参考以下文章
捕获具有数据属性的 html 元素 - javascript ".querySelector"
Javascript .querySelector 通过 innerTEXT 查找 <div>
javascript高级选择器querySelector和querySelectorAll
JavaScript中querySelector()和getElementById()(getXXXByXX)的区别