是否可以通过JavaScript引用注释元素/块?

Mor*_*eng 21 javascript dom comments

这听起来有点疯狂,但我想知道是否有可能获得对comment元素的引用,以便我可以使用JavaScript动态替换其他内容.

<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content"></div>
<!-- sidebar place holder: some id-->
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

在上面的页面中,我可以参考注释块并将其替换为本地存储中的某些内容吗?

我知道我可以有一个div占位符.只是想知道它是否适用于评论块.谢谢.

hyp*_*lug 27

var findComments = function(el) {
    var arr = [];
    for(var i = 0; i < el.childNodes.length; i++) {
        var node = el.childNodes[i];
        if(node.nodeType === 8) {
            arr.push(node);
        } else {
            arr.push.apply(arr, findComments(node));
        }
    }
    return arr;
};

var commentNodes = findComments(document);

// whatever you were going to do with the comment...
console.log(commentNodes[0].nodeValue);
Run Code Online (Sandbox Code Playgroud)

  • 有一个`Node.COMMENT_NODE`常量,您可以使用它来测试commentar而不是`8` (4认同)
  • 谢谢.但DOM树的遍历必须花费很多.所以,我们最好不要将评论用作占位符. (3认同)
  • 在ie8中未定义Node.COMMENT_NODE.如果这是你的目标,请保留数字8. (2认同)

min*_*.dk 12

关于使用注释作为占位符似乎存在合法(性能)问题 - 例如,没有可以匹配注释节点的CSS选择器,因此您将无法使用例如查询它们document.querySelectorAll(),这使得它既复杂又位置慢评论元素.

我的问题是,是否有另一个我可以放置内联的元素,它没有任何明显的副作用?我见过一些人使用<meta>标签,但我调查了这一点,并使用它<body>是无效的标记.

所以我决定使用<script>标签.

使用自定义type属性,因此它实际上不会作为脚本执行,并使用data-属性来初始化占位符的脚本所需的任何初始化数据.

例如:

<script type="placeholder/foo" data-stuff="whatevs"></script>
Run Code Online (Sandbox Code Playgroud)

然后只需查询这些标签 - 例如:

document.querySelectorAll('script[type="placeholder/foo"]')
Run Code Online (Sandbox Code Playgroud)

然后根据需要替换它们 - 这是一个简单的DOM示例.

请注意,placeholder在此示例中不是任何已定义的"真实"事物 - 您应该将其替换为例如vendor-name以确保您type不会与任何"真实"冲突.

  • 另一个用作占位符的好标签可能是“&lt;template&gt;”或“&lt;font&gt;”或任何自定义标签,例如“&lt;my-boundary-marker&gt;”。 (2认同)

Jos*_*nox 9

建立Hyperslug的答案,你可以通过使用堆栈而不是函数递归来加快速度.如此jsPerf所示,Windows上的Chrome 36上的函数递归速度降低了42%,IE8兼容模式下的IE11的函数递归速度降低了71%.在边缘模式下IE11的运行速度似乎慢了约20%,但在所有其他测试情况下运行速度更快.

function getComments(context) {
    var foundComments = [];
    var elementPath = [context];
    while (elementPath.length > 0) {
        var el = elementPath.pop();
        for (var i = 0; i < el.childNodes.length; i++) {
            var node = el.childNodes[i];
            if (node.nodeType === Node.COMMENT_NODE) {
                foundComments.push(node);
            } else {
                elementPath.push(node);
            }
        }
    }

    return foundComments;
}
Run Code Online (Sandbox Code Playgroud)

或者像在TypeScript中一样:

public static getComments(context: any): Comment[] {
    var foundComments = [];
    var elementPath = [context];
    while (elementPath.length > 0) {
        var el = elementPath.pop();
        for (var i = 0; i < el.childNodes.length; i++) {
            var node = el.childNodes[i];
            if (node.nodeType === Node.COMMENT_NODE) {
                foundComments.push(node);
            } else {
                elementPath.push(node);
            }
        }
    }

    return foundComments;
}
Run Code Online (Sandbox Code Playgroud)


mem*_*ems 7

有一个用于文档节点遍历的 API Document#createNodeIterator()

var nodeIterator = document.createNodeIterator(
    document.body,
    NodeFilter.SHOW_COMMENT
);

// Replace all comment nodes with a div
while(nodeIterator.nextNode()){
    var commentNode = nodeIterator.referenceNode;
    var id = (commentNode.textContent.split(":")[1] || "").trim();
    var div = document.createElement("div");
    div.id = id;
    commentNode.parentNode.replaceChild(div, commentNode);
}
Run Code Online (Sandbox Code Playgroud)
#header,
#content,
#some_id{
  margin: 1em 0;
  padding: 0.2em;
  border: 2px grey solid;
}

#header::after,
#content::after,
#some_id::after{
  content: "DIV with ID=" attr(id);
}
Run Code Online (Sandbox Code Playgroud)
<html>
<head>
</head>
<body>
<div id="header"></div>
<div id="content"></div>
<!-- sidebar placeholder: some_id -->
</body>
</html>
Run Code Online (Sandbox Code Playgroud)


编辑:使用NodeIterator而不是TreeWalker