是否可以通过 JavaScript 获取对评论元素/块的引用?
这听起来有点疯狂,但我想知道是否可以引用注释元素,以便我可以用 JavaScript 动态地将其替换为其他内容。
<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content"></div>
<!-- sidebar place holder: some id-->
</body>
</html>
在上面的页面中,我可以引用评论块并将其替换为本地存储中的某些内容吗?
我知道我可以有一个 div 占位符。只是想知道它是否适用于评论区。 谢谢。
This sounds a little crazy, but I'm wondering whether possible to get reference to comment element so that I can dynamically replace it other content with JavaScript.
<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content"></div>
<!-- sidebar place holder: some id-->
</body>
</html>
In above page, can I get reference to the comment block and replace it with some content in local storage?
I know that I can have a div place holder. Just wondering whether it applies to comment block.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
使用注释作为占位符似乎存在合理的(性能)问题 - 首先,没有可以匹配注释节点的 CSS 选择器,因此您将无法使用例如
document.querySelectorAll(),这使得定位注释元素既复杂又缓慢。
我的问题是,是否有另一个元素可以内联放置,并且没有任何明显的副作用?我看到有些人使用
标记,但我对此进行了研究,发现在
中使用它不是有效的标记。
所以我选择了
标签。
使用自定义
type
属性,因此它实际上不会作为脚本执行,并使用data-
属性来获取将初始化您的脚本所需的任何初始化数据占位符。例如:
然后简单地查询这些标签 - 例如:
然后根据需要替换它们 - 这是一个简单的 DOM 示例。
请注意,此示例中的
placeholder
并不是任何定义的“真实”事物 - 您应该将其替换为vendor-name
以确保您的type
> 不会与任何“真实”的东西发生碰撞。It seems there are legitimate (performance) concerns about using comments as placeholders - for one, there's no CSS selector that can match comment nodes, so you won't be able to query them with e.g.
document.querySelectorAll()
, which makes it both complex and slow to locate comment elements.My question then was, is there another element I can place inline, that doesn't have any visible side-effects? I've seen some people using the
<meta>
tag, but I looked into that, and using that in<body>
isn't valid markup.So I settled on the
<script>
tag.Use a custom
type
attribute, so it won't actually get executed as a script, and usedata-
attributes for any initialization data required by the script that's going to initialize your placeholders.For example:
Then simply query those tags - e.g.:
Then replace them as needed - here's a plain DOM example.
Note that
placeholder
in this example isn't any defined "real" thing - you should replace that with e.g.vendor-name
to make sure yourtype
doesn't collide with anything "real".有一个用于文档节点遍历的 API:
Document# createNodeIterator()
:编辑:使用 NodeIterator 而不是 TreeWalker
There is an API for document nodes traversal:
Document#createNodeIterator()
:Edit: use a NodeIterator instead of a TreeWalker
基于 hyperslug 的答案,您可以通过使用堆栈而不是函数递归来使其运行得更快。如jsPerf所示,在 Windows 上的 Chrome 36 上,函数递归速度慢了 42%在 IE8 兼容模式下,IE11 为 71%。在 IE11 的边缘模式下,它的运行速度似乎慢了约 20%,但在所有其他测试情况下运行速度更快。
或者像 TypeScript 中那样:
Building off of hyperslug's answer, you can make it go faster by using a stack instead of function recursion. As shown in this jsPerf, function recursion is 42% slower on my Chrome 36 on Windows and 71% with IE11 in IE8 compatibility mode. It appears to run about 20% slower in IE11 in edge mode but faster in all other cases tested.
Or as done in TypeScript:
使用 document.evaluate 和 xPath:
根据我的测试,使用 xPath 比 treeWalker 更快:
https://jsben.ch/Feagf
Using document.evaluate and xPath:
from my testing, using xPath is faster than treeWalker:
https://jsben.ch/Feagf
如果您使用 jQuery,则可以执行以下操作来获取所有注释节点
如果您只想要正文的注释节点,请使用
如果您希望注释字符串作为数组,则可以使用
map
:If you use jQuery, you can do the following to get all comment nodes
If you only want the comments nodes of the body, use
If you want the comment strings as an array you can then use
map
:如果您只想从文档或文档的一部分获取所有注释的数组,那么这是我发现在现代 JavaScript 中实现此目的的最有效方法。
我在 Chrome 80 中每秒执行超过 50,000 次操作,而堆栈和递归方法在 Chrome 80 中每秒执行的操作均少于 5,000 次。我在 node.js 中需要处理数以万计的复杂文档,这对我来说效果最好。
https://jsperf.com/getcomments/6
If you just want to get an array of all comments from a document or part of a document, then this is the most efficient way I've found to do that in modern JavaScript.
I am getting over 50,000 operations per second in Chrome 80 and the stack and recursion methods both get less than 5,000 operations per second in Chrome 80. I had tens of thousands of complex documents to process in node.js and this worked the best for me.
https://jsperf.com/getcomments/6
这是一个老问题,但这是我对 DOM“占位符”的两点看法
IMO 评论元素非常适合这项工作(有效的 html,不可见,并且不会以任何方式误导)。
然而,如果您以相反的方式构建代码,则不需要遍历 dom 来查找注释。
我建议使用以下方法:
用您选择的标记标记您想要“控制”的位置(例如具有特定类的 div 元素)
以通常的方式查找占位符(querySelector/classSelector 等)
var placeholders = document.querySelectorAll('placeholder');
var refArray = [];
[...占位符].forEach(函数(占位符){
var comment = document.createComment('这是一个占位符');
refArray.push( placeholder.parentNode.replaceChild(comment, placeholder) );
});
在此阶段,您呈现的标记应如下所示:
将第二个注释替换为标题
let header = document.createElement('h1');
header.innerText = "我是头条!";
refArray[1].parentNode.replaceChild(标题,refArray[1]);
This is an old question, but here's my two cents on DOM "placeholders"
IMO a comment element is perfect for the job (valid html, not visible, and not misleading in any way).
However, traversing the dom looking for comments is not necessary if you build your code the other way around.
I would suggest using the following method:
Mark the places you want to "control" with markup of your choice (e.g a div element with a specific class)
Find the placeholders the usual way (querySelector/classSelector etc)
var placeholders = document.querySelectorAll('placeholder');
var refArray = [];
[...placeholders].forEach(function(placeholder){
var comment = document.createComment('this is a placeholder');
refArray.push( placeholder.parentNode.replaceChild(comment, placeholder) );
});
at this stage your rendered markup should look like this:
replace the second comment with a headline
let headline = document.createElement('h1');
headline.innerText = "I am a headline!";
refArray[1].parentNode.replaceChild(headline,refArray[1]);
我建议使用
createTreeWalker
和内部的自定义过滤器:然后:
I recommend to use the
createTreeWalker
and a custom filter inside:Then: