0

我正在写一个模板引擎。我正在尝试按需更新 innerHTML 的某些部分,例如在模型更新时。

据我发现,我可以通过两种方式更新部分:

  1. 用父元素包装 html 部分,获取该元素并重新生成它的内容并重新插入。然而,包装可能会破坏 css 规则等等,并且会修改用户当前的 html 结构。

  2. 在前后发表评论,发现要更新的部分是什么,然后替换那个确切的部分。这工作正常,但是当我这样做时:

    document.documentElement.innerHTML = innerHTML.substring(0, indexStart) + template + innerHTML.substring(indexEnd);

整个 dom 被一个新字符串替换,来自其他部分的所有事件绑定都将丢失。

那么有没有人对我如何使用评论策略或类似策略仅替换部分 html 有更好的了解?

示例

<html>
  <head>

  </head>

  <body>

    <div>something</div>

    <!-- id:321312321 -->
      <div>Replace all within this comment space</div>
      <div>1</div>
      <div>2</div>
      <div>3</div>
    <!-- id:321312321 -->

  </body>
</html>
4

1 回答 1

0

可用于示例:

<html>
  <head></head>
  <body>
    <div>something</div>

    <!-- id:321312321 -->
      <div>Replace all within this comment space</div>
      <div>1</div>
      <div>2</div>
      <div>3</div>
    <!-- id:321312321 -->

  </body>
</html>

作为:

commentReplaceBetween("<div>1</div>", " id:321312321 ");

将导致:

<html>
  <head></head>
  <body>
    <div>something</div>

    <!-- id:321312321 -->
    <div>1</div>
    <!-- id:321312321 -->

  </body>
</html>

代码:

function commentReplaceBetween(template, commentContent) {
        var div       = document.createElement("div");
        div.innerHTML = template;

        // Find our comment first
        var comment    = nodeCommentFind(document.documentElement, commentContent);
        var parentNode = comment.parentNode;
        var sibling    = comment.nextSibling;

        // Delete all contents in between
        while ( sibling ) {
                if ( nodeCommentContentMatch(sibling, commentContent) ) {
                        break;
                } else {
                        var tmp = sibling;
                        sibling = sibling.nextSibling;
                        parentNode.removeChild(tmp);
                }
        }

        // Then append our elements afterw
        var child, children  = div.childNodes;
        for ( var i = 0; i < children.length; i++) {
                child = children[i];

                // See:
                // http://www.javascriptkit.com/domref/nodetype.shtml
                // and
                // http://msdn.microsoft.com/en-us/library/windows/desktop/ms764649(v=vs.85).aspx
                if ( child.nodeType === 1 || child.nodeType === 7 || child.nodeType === 8 || child.nodeType === 11 ) {
                        // Sibling here should be the last comment, otherwise the entire page have been incorrectly deleted.
                        parentNode.insertBefore(child, sibling);
                }
        }
}

var cacheComment = {};
function nodeCommentFind(node, commentContent) {
        var child = cacheComment[commentContent];
        if ( child ) {
                return child;
        }
        else {
                return nodeCommentFindRecurse(node, commentContent);
        }
}

function nodeCommentFindRecurse(node, commentContent) {
        var children = node.childNodes;

        var child, returns;
        for(var i = 0; i < children.length; i++) {
                child = children[i];

                if( nodeCommentContentMatch(child, commentContent) ) {
                        cacheComment[commentContent] = child;
                        return child;
                }
                else if ( child.hasChildNodes && child.childNodes ) {
                        returns = nodeCommentFindRecurse(child, commentContent);
                        if ( returns ) return returns;
                }
        }
}

function nodeCommentIs(node) {
        return node.nodeType === 8;
}
function nodeCommentContentMatch(node, commentContent) {
        return nodeCommentIs(node) && node.nodeValue === commentContent;
}

/////////////////////////////////////////////////////////////////////
////////////////////////// BONUS INFORMATION ////////////////////////
/////////////////////////////////////////////////////////////////////

我的commentReplaceBetween 是这样调用的

commentReplaceBetween(commentContent)(template);

所以我的实际commentReplaceBetween 函数被包装起来,看起来像这样:

function commentReplaceBetween(commentContent) {
        return function(template) {
                var div       = document.createElement("div");
                div.innerHTML = template;

                // Find our comment first
                var comment    = nodeCommentFind(document.documentElement, commentContent);
                var parentNode = comment.parentNode;
                var sibling    = comment.nextSibling;

                // Delete all contents in between
                while ( sibling ) {
                        if ( nodeCommentContentMatch(sibling, commentContent) ) {
                                break;
                        } else {
                                var tmp = sibling;
                                sibling = sibling.nextSibling;
                                parentNode.removeChild(tmp);
                        }
                }

                // Then append our elements afterw
                var child, children  = div.childNodes;
                for ( var i = 0; i < children.length; i++) {
                        child = children[i];

                        // See:
                        // http://www.javascriptkit.com/domref/nodetype.shtml
                        // and
                        // http://msdn.microsoft.com/en-us/library/windows/desktop/ms764649(v=vs.85).aspx
                        if ( child.nodeType === 1 || child.nodeType === 7 || child.nodeType === 8 || child.nodeType === 11 ) {
                                // Sibling here should be the last comment, otherwise the entire page have been incorrectly deleted.
                                parentNode.insertBefore(child, sibling);
                        }
                }
        };
}
于 2013-08-23T17:40:17.803 回答