InnerHTML追加而不是替换

11

我正在使用这段代码通过 AJAX 请求更新一个 div

var xmlhttp;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp = new XMLHttpRequest();
} else { // code for IE6, IE5
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        document.getElementById("some_id").innerHTML += xmlhttp.responseText;
    }
}
xmlhttp.open("GET", "http://example.com/");
xmlhttp.setRequestHeader('Content-Type', 'utf8');
xmlhttp.send();

一切都运作正常,问题在于当id为some_iddiv内有很多内容时,我会看到内容消失,然后在执行AJAX请求后更新后再次出现。

我认为这是因为

document.getElementById("some_id").innerHTML += xmlhttp.responseText;

删除并用先前的innerHTML加上新内容替换div,导致“先前的内容→空白→更新的内容”行为。

是否有一种方法可以将新内容追加到div中,而不是用新内容完全替换其整个内容?


你是在使用 jQuery 还是本地的 JavaScript? - Raghu
1
尝试添加子元素而不是替换整个HTML。 - Milad Hosseinpanahi
如果您正在使用jQuery,那么您绝不能直接使用innerHTML,因为它不会删除事件处理程序。请改用jQuery的.html选项,否则您将遇到大量的内存泄漏问题(是的,在JavaScript中确实存在这种情况)。 - Dave
@Dave 是的,这是一个 Joomla 网站,模板有很多嵌套的 div。 - BackSlash
听起来你可能让渲染引擎崩溃了。尽量减少页面上的代码量。一些网站会用大型空白div替换视口上方/下方的内容,以此来避免这种情况(将实际内容作为仅由JavaScript知道的DOM存活,即不包含在文档中)。 - Dave
显示剩余2条评论
3个回答

13
假设 htmlhttp.responseText 是一个节点:
document.getElementById("some_id").appendChild(xmlhttp.responseText);

如果您只有一串HTML字符串(这似乎很可能),那么:

var newElement = document.createElement('div');
newElement.innerHTML = xmlhttp.responseText;
document.getElementById("some_id").appendChild(newElement);

另一方面,如果您必须从字符串中添加新元素:

// getting a reference to the relevant element we're adding to:
var container = document.getElementById("some_id"),
    // creating a new element to contain the 'xmlhttp.responseText'
    newElement = document.createElement('div');
// setting the innerHTML of the 'newElement' to whatever 'xmlhttp.responseText' is:
newElement.innerHTML = xmlhttp.responseText;

/* (repeatedly) removing the firstChild, and appending it to the 'container',
   of the 'newElement' until it's empty: */
while (newElement.firstChild) {
    container.appendChild(newElement.firstChild);
}
// removing the now empty 'newElement':
newElement.parentNode.removeChild(newElement);

参考资料:


如果它是一堆节点呢? - BackSlash
然后,您可以迭代每个节点并重复使用 appendChild(),或将它们包装在一个节点中并附加节点。如果没有看到您的 xmlhttp.responseText 变量中的示例,很难具体回答以解决您的用例。 - David Thomas
看到更新了,如果我必须在当前的 div 上追加内容而不创建新的 div 怎么办? - BackSlash
htmlhttp.responseText 很可能是一个字符串。 - Salman A
1
@BackSlash:那么请给出你正在处理的示例 - David Thomas
显示剩余3条评论

9
您可以使用 Element.insertAdjacentHTML() 方法。

insertAdjacentHTML() 方法将指定的文本解析为 HTML 或 XML,并将生成的节点插入到 DOM 树中的指定位置。它不会重新解析正在使用的元素,因此不会破坏元素内部的现有元素。这样做可以避免额外的序列化步骤,使其比直接操作 innerHTML 更快。

我想您可能会这样做:
const div = document.getElementById("some_id");
div.insertAdjacentHTML('beforeend', xmlhttp.responseText);;

4
old_html = document.getElementById("some_id").innerHTML;
document.getElementById("some_id").innerHTML = old_html+xmlhttp.responseText;

这与我的有何不同? - BackSlash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接