【问题标题】:Appending HTML string to the DOM将 HTML 字符串附加到 DOM
【发布时间】:2011-11-11 17:26:33
【问题描述】:

如何附加 HTML 字符串,例如

var str = '<p>Just some <span>text</span> here</p>';

发送到 ID 为 test&lt;div&gt;

(顺便说一句,div.innerHTML += str; 是不可接受的。)

【问题讨论】:

    标签: javascript html dom browser


    【解决方案1】:

    使用insertAdjacentHTML 哪个is supported in all current browsers

    div.insertAdjacentHTML( 'beforeend', str );
    

    位置参数beforeend 将添加到元素内部,在其最后一个子元素之后。

    现场演示: http://jsfiddle.net/euQ5n/

    【讨论】:

    • @alex 是同一个概念:解析 HTML 字符串并将其放入 DOM。但功能不同 - innerHTML 将字符串放入元素中(替换所有子元素),而 insertAdjacentHTML 将其 (1) 放在元素之前,(2) 元素之后,(3) 放在第一个元素之前的元素内子元素,或 (4) 在最后一个子元素之后的元素内。
    • @alex insertAdjacentHTML 比附加到innerHTML 更快,因为insertAdjacentHTML 不会序列化和重新解析元素的现有子元素。
    • 另外,insertAdjacentHTML 维护更改的表单元素的值,而附加到 innerHTML 会重建元素并丢失所有表单上下文。
    【解决方案2】:

    性能

    AppendChild(E) 在 chrome 和 safari 上比其他解决方案快 2 倍以上,insertAdjacentHTML(F) 在 firefox 上最快。 innerHTML= (B)(不要与 += (A) 混淆)是所有浏览器上的第二个快速解决方案,它比 E 和 F 更方便。

    详情

    在 Chrome 75.0.3770(64 位)、Safari 11.1.0 (13604.5.6)、Firefox 67.0.0(64 位)上设置环境 (2019.07.10) MacOs High Sierra 10.13.4

    • 在 Chrome E 上(每秒 140k 次操作)最快,B (47k) 和 F (46k) 次之,A (332) 最慢
    • 在 firefox 上 F (94k) 最快,然后 B(80k)、D (73k)、E(64k)、C (21k) 最慢是 A(466)
    • 在 Safari 上 E(207k) 最快,然后是 B(89k)、F(88k)、D(83k)、C(25k),最慢的是 A(509)

    你可以在你的机器上重播测试here

    function A() {    
      container.innerHTML += '<p>A: Just some <span>text</span> here</p>';
    }
    
    function B() {    
      container.innerHTML = '<p>B: Just some <span>text</span> here</p>';
    }
    
    function C() {    
      $('#container').append('<p>C: Just some <span>text</span> here</p>');
    }
    
    function D() {
      var p = document.createElement("p");
      p.innerHTML = 'D: Just some <span>text</span> here';
      container.appendChild(p);
    }
    
    function E() {    
      var p = document.createElement("p");
      var s = document.createElement("span"); 
      s.appendChild( document.createTextNode("text ") );
      p.appendChild( document.createTextNode("E: Just some ") );
      p.appendChild( s );
      p.appendChild( document.createTextNode(" here") );
      container.appendChild(p);
    }
    
    function F() {    
      container.insertAdjacentHTML('beforeend', '<p>F: Just some <span>text</span> here</p>');
    }
    
    A();
    B();
    C();
    D();
    E();
    F();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    This snippet only for show code used in test (in jsperf.com) - it not perform test itself. 
    <div id="container"></div>

    【讨论】:

    • 可读性通常比性能更重要。但是感谢您的腿部工作。
    • @Jay 优化只应在需要时使用,并且通常必须有丰富的注释
    • 使用 innerHTML 似乎不好,因为浏览器必须再次解析整个 HTML,而不是添加到尾部
    【解决方案3】:

    这可以接受吗?

    var child = document.createElement('div');
    child.innerHTML = str;
    child = child.firstChild;
    document.getElementById('test').appendChild(child);
    

    jsFiddle.

    但是Neil's answer 是更好的解决方案。

    【讨论】:

    • @Šime 使用 DOM API 总是 感觉就像是 hack :P 您是否希望在 没有 innerHTMLinnerHTML 的情况下反序列化字符串?跨度>
    • 嗯,是的,如果有其他方法可以利用浏览器的 HTML 解析器,我很想知道...
    • @Šime - 我认为只有两种方法可以利用浏览器的 HTML 解析器,innerHTML 和 document.write。如果你认为 innerHTML 是一种 hack ...
    • @Alohci 还有另一种方式:insertAdjacentHTML
    • @Šime-谢谢。我找到了 WHATWG 版本。它在DOM Parsing and Serialization 规范中。它表明除了innerHTML 和insertAdjacentHTML,还有outerHTML,我认为还有createContextualFragment。
    【解决方案4】:

    想法是在中间元素上使用innerHTML,然后通过appendChild 将其所有子节点移动到您真正想要的位置。

    var target = document.getElementById('test');
    var str = '<p>Just some <span>text</span> here</p>';
    
    var temp = document.createElement('div');
    temp.innerHTML = str;
    while (temp.firstChild) {
      target.appendChild(temp.firstChild);
    }
    

    这避免了清除 div#test 上的任何事件处理程序,但仍允许您附加 HTML 字符串。

    【讨论】:

      【解决方案5】:

      正确的方法是使用insertAdjacentHTML。在 Firefox 8 之前的版本中,如果您的 str 不包含 script 标签,您可以回退到使用 Range.createContextualFragment

      如果您的str 包含script 标签,则需要在插入片段之前从createContextualFragment 返回的片段中删除script 元素。否则,脚本将运行。 (insertAdjacentHTML 标记脚本不可执行。)

      【讨论】:

      • 感谢您提及createContextualFragment 。我一直在寻找一种方法,让一些带有脚本的 html 包含仅在用户同意设置 cookie 时才运行。
      【解决方案6】:

      快速破解


      <script>
      document.children[0].innerHTML="<h1>QUICK_HACK</h1>";
      </script>
      

      用例

      1:另存为 .html 文件并在 chrome 或 firefox 或 edge 中运行。 (IE 不会工作)

      2:在http://js.do中使用

      在行动: http://js.do/HeavyMetalCookies/quick_hack

      用 cmets 分解:

      <script>
      
      //: The message "QUICK_HACK" 
      //: wrapped in a header #1 tag.
      var text = "<h1>QUICK_HACK</h1>";
      
      //: It's a quick hack, so I don't
      //: care where it goes on the document,
      //: just as long as I can see it.
      //: Since I am doing this quick hack in
      //: an empty file or scratchpad, 
      //: it should be visible.
      var child = document.children[0];
      
      //: Set the html content of your child
      //: to the message you want to see on screen.
      child.innerHTML = text;
      
      </script>
      

      我发帖的原因:

      JS.do 有两个必备:

      1. 没有自动完成
      2. 垂直显示器友好

      但不显示 console.log 消息。 来这里寻找快速解决方案。 我只想看看结果 几行暂存代码, 其他解决方案工作量太大。

      【讨论】:

        【解决方案7】:

        为什么不能接受?

        document.getElementById('test').innerHTML += str

        这将是教科书的做法。

        【讨论】:

        • 它会将kill event handlers 附加到#test。这通常是不可取的。
        • 有趣的是它这样做了。似乎真的不合逻辑。
        • 如果您考虑将 HTML 序列化为字符串,然后将 HTML 设置回来,这是合乎逻辑的。
        • 我想 JavaScript 必须再次运行才能重置事件处理程序。很公平。
        • @Nick 您不想将 DOM 的一部分进行字符串化(序列化),以便您可以将其与另一个字符串连接起来,然后将整个内容解析回 DOM。正如亚历克斯所说,序列化不会记录绑定的事件处理程序(除其他外)。即使他的序列化可以捕获所有内容,您仍然不想这样做。
        【解决方案8】:

        这个可以解决

         document.getElementById("list-input-email").insertAdjacentHTML('beforeend', '<div class=""><input type="text" name="" value="" class="" /></div>');
        

        【讨论】:

        • 欢迎来到堆栈溢出。请解释您的代码作为答案的一部分,以提供一些上下文,而不仅仅是粘贴一长串代码。虽然你理解它,但其他人可能不理解它在做什么。
        【解决方案9】:

        InnerHTML 清除现有节点的所有数据,如事件

        append child with firstChild 仅将第一个子元素添加到 innerHTML。例如,如果我们必须附加:

         <p>text1</p><p>text2</p>
        

        只有 text1 会显示

        这个呢:

        通过追加子元素将特殊标签添加到innerHTML,然后通过删除我们创建的标签来编辑outerHTML。不知道它有多聪明,但它对我有用 或者您可以将outerHTML 更改为innerHTML,这样它就不必使用函数replace

        function append(element, str)
        {
        
          var child = document.createElement('someshittyuniquetag');
        		
          child.innerHTML = str;
        
          element.appendChild(child);
        
          child.outerHTML = child.outerHTML.replace(/<\/?someshittyuniquetag>/, '');
        
        // or Even child.outerHTML = child.innerHTML
        
        
          
        }
        <div id="testit">
        This text is inside the div
        <button onclick="append(document.getElementById('testit'), '<button>dadasasdas</button>')">To div</button>
        <button onclick="append(this, 'some text')">to this</button>
        </div>

        【讨论】:

          【解决方案10】:

          最短 - 18 个字符(不要混淆+=(OP 提及)和= 更多详细信息here

          test.innerHTML=str
          

          var str = '<p>Just some <span>text</span> here</p>';
          
          test.innerHTML=str
          &lt;div id="test"&gt;&lt;/div&gt;

          【讨论】:

          • 问题是关于追加,而不是替换
          猜你喜欢
          • 2017-12-10
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 2020-03-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多