【问题标题】:Changing HTML in JavaScript without innerHTML在没有 innerHTML 的情况下更改 JavaScript 中的 HTML
【发布时间】:2019-04-17 21:17:51
【问题描述】:

假设我的代码非常简单,如下所示:

let content = "";

for(let i=0; i<array.length; i++){
    content+='<h1>array[i]</h1>';
}

document.getElementById('some_id').innerHTML = content;

我不喜欢将 HTML 放入我的 JavaScript 代码的想法,但我不知道在不使用 innerHTML、JQuery 的 html() 方法或简单地创建新 DOM 的情况下将元素插入 DOM 的任何其他方法以编程方式添加元素。

在业界或最佳实践中,从 JavaScript 插入 HTML 元素的最佳方式是什么?

提前致谢!

【问题讨论】:

  • 您可以使用document.createElementnodeYouWishToExtend.appendChild(nodeYouCreated)。对于另一种方法,您可以查看 React、Angular、Vue、Knockout 等框架。
  • 最佳实践是创建 DOM 元素对象并将文本插入到这些元素中以防范 XSS
  • ps 你的预感认为在 javascript 中编写 html 是“糟糕的”,这在很大程度上是正确的。我不知道array 来自哪里,但假设用户可以更改它,他们可能会潜入一些“不安全”的值。例如&lt;script type="text/javascript"&gt;doBadThing()&lt;/script&gt;。除非你要转义你的输入,或者使用一个库,否则你不应该直接使用用户来源的输入来设置 innerHTML。
  • content+='&lt;h1&gt;array[i]&lt;/h1&gt;'; 不会评估 array[i] 而是将其打印为文本。

标签: javascript html dom innerhtml


【解决方案1】:

您可以使用 DOMParser 和 ES6 字符串文字:

const template = text => (
`
<div class="myClass">
    <h1>${text}</h1>
</div>
`);

您可以在内存中创建一个片段:

const fragment = document.createDocumentFragment();
const parser = new DOMParser();
const newNode = parser.parseFromString(template('Hello'), 'text/html');
const els = newNode.documentElement.querySelectorAll('div');
for (let index = 0; index < els.length; index++) {
  fragment.appendChild(els[index]);  
}
parent.appendChild(fragment);

由于文档片段在内存中而不是主 DOM 树的一部分,因此将子片段附加到它不会导致页面重排(计算元素的位置和几何形状)。从历史上看,使用文档片段可能会带来更好的性能。

来源:https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

基本上你可以使用任何你想要的模板,因为它只是一个返回一个字符串的函数,你可以将它输入到解析器中。

希望对你有帮助

【讨论】:

    【解决方案2】:

    你可以使用createElement()方法

    在 HTML 文档中,document.createElement() 方法创建由 tagName 指定的 HTML 元素,如果无法识别 tagName,则创建 HTMLUnknownElement。

    这是一个例子,

    document.body.onload = addElement;
    
    function addElement () { 
      // create a new div element 
      var newDiv = document.createElement("div"); 
      // and give it some content 
      var newContent = document.createTextNode("Hi there and greetings!"); 
      // add the text node to the newly created div
      newDiv.appendChild(newContent);  
    
      // add the newly created element and its content into the DOM 
      var currentDiv = document.getElementById("div1"); 
      document.body.insertBefore(newDiv, currentDiv); 
    }
    <!DOCTYPE html>
    <html>
    <head>
      <title>||Working with elements||</title>
    </head>
    <body>
      <div id="div1">The text above has been created dynamically.</div>
    </body>
    </html>

    【讨论】:

      【解决方案3】:

      一种使用 JavaScript 的 insertAdjacentHTML 方法插入 HTML 元素的灵活且更快速(高效)的方法。它允许您准确指定放置元素的位置。可能的位置值是:

      • 'beforebegin'
      • 'afterbegin'
      • 'beforeend'
      • 'afterend'

      像这样:

       document.getElementById("some_id").insertAdjacentElement("afterbegin", content);
      

      Here's a Fiddle example

      【讨论】:

        【解决方案4】:

        以编程方式而不是通过 HTML 创建元素应该具有预期的效果。

        const parent = document.getElementById('some_id');
        // clear the parent (borrowed from https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript)
        
        while (parent.firstChild) {
            parent.removeChild(parent.firstChild);
        }
        
        // loop through array and create new elements programmatically
        for(let i=0; i<array.length; i++){
            const newElem = document.createElement('h1');
            newElem.innerText = array[i];
            parentElement.appendChild(newElem);
        }
        

        【讨论】:

        • 如果你有很多节点,我发现使用 while 循环清除子节点会更慢,我一直喜欢这个 el.parentNode.replaceChild(el.cloneNode(false), el ) 使用 false 标志克隆元素,该标志会生成没有任何子元素的副本,然后将元素替换为更精简的 self。
        • 我确实认为它看起来更慢,但这是否处理孩子不存在的情况?
        猜你喜欢
        • 2018-01-21
        • 1970-01-01
        • 1970-01-01
        • 2012-04-01
        • 2019-11-09
        • 2015-03-05
        • 2015-08-11
        • 2012-05-26
        • 1970-01-01
        相关资源
        最近更新 更多