在没有 innerHTML 的情况下更改 JavaScript 中的 HTML
Posted
技术标签:
【中文标题】在没有 innerHTML 的情况下更改 JavaScript 中的 HTML【英文标题】:Changing HTML in JavaScript without innerHTML 【发布时间】: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.createElement
和nodeYouWishToExtend.appendChild(nodeYouCreated)
。对于另一种方法,您可以查看 React、Angular、Vue、Knockout 等框架。
最佳实践是创建 DOM 元素对象并将文本插入到这些元素中以防范 XSS
ps 你的预感认为在 javascript 中编写 html 是“糟糕的”,这在很大程度上是正确的。我不知道array
来自哪里,但假设用户可以更改它,他们可能会潜入一些“不安全”的值。例如<script type="text/javascript">doBadThing()</script>
。除非你要转义你的输入,或者使用一个库,否则你不应该直接使用用户来源的输入来设置 innerHTML。
content+='<h1>array[i]</h1>';
不会评估 array[i]
而是将其打印为文本。
【参考方案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://***.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。 我确实认为它看起来更慢,但这是否处理孩子不存在的情况?以上是关于在没有 innerHTML 的情况下更改 JavaScript 中的 HTML的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript:如何在没有 innerHTML 的情况下替换元素内的代码
如何在没有 innerHTML = ""; 的情况下清除 div 的内容
在不更改 `src=` 的情况下重新加载 iFrame(同域)