为了账号安全,请及时绑定邮箱和手机立即绑定

为什么y.innerHTML = x.innerHTML; 被避免?

为什么y.innerHTML = x.innerHTML; 被避免?

青春有我 2019-11-28 13:14:51
假设我们x在页面上有一个DIV ,并且想要将该DIV的内容复制(“复制粘贴”)到另一个DIV中y。我们可以这样做:y.innerHTML = x.innerHTML;或使用jQuery:$(y).html( $(x).html() );但是,看来此方法不是一个好主意,应避免使用。(1)为什么要避免这种方法?(2)应该怎么做呢?更新:为了解决这个问题,我们假设DIV中没有ID为ID的元素x。(对不起,我忘了在原始问题中介绍此案。)结论:我已经在下面发布了我对这个问题的答案(如我最初的意图)。现在,我还计划接受我自己的答案:P,但是孤独某日的答案是如此惊人,以至于我不得不接受它。
查看完整描述

3 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

这种将HTML元素从一个地方“复制”到另一个地方的方法是对浏览器功能的错误理解的结果。浏览器不会将HTML文档保存在内存中的某个位置,而是会根据来自JavaScript的命令反复修改HTML。


当浏览器首次加载页面时,它将解析 HTML文档并将其转换为DOM结构。这是遵循W3C标准的对象之间的关系(嗯,主要是...)。从那时起,原始的HTML是完全多余的。浏览器不在乎原始的HTML结构是什么。它对网页的理解是从中创建的DOM结构。如果您的HTML标记不正确/无效,则网络浏览器会通过某种方式对其进行更正;DOM结构不会以任何方式包含无效代码。


基本上,HTML应该被视为对DOM结构进行序列化的一种方式,以使其可以通过Internet传递或存储在本地文件中。


因此,不应将其用于修改现有网页。DOM(文档对象模型)具有用于更改页面内容的系统。这是基于节点的关系,而不是基于HTML序列化。因此,当你添加一个li到ul,你有这两个选项(假设ul是列表元素):


// option 1: innerHTML

ul.innerHTML += '<li>foobar</li>';


// option 2: DOM manipulation

var li = document.createElement('li');

li.appendChild(document.createTextNode('foobar'));

ul.appendChild(li);

现在,第一个选项看起来简单很多,但这只是因为浏览器为您提供了很多抽象的东西:在内部,浏览器必须将元素的子代转换为字符串,然后附加一些内容,然后将字符串转换回DOM结构。第二个选项对应于浏览器对正在发生的事情的本机理解。


第二个主要考虑因素是考虑HTML的局限性。考虑网页时,并非与元素相关的所有内容都可以序列化为HTML。例如,与绑定的事件处理程序x.onclick = function();或x.addEventListener(...)不会在中复制的事件处理程序innerHTML,因此不会在它们之间进行复制。因此,其中的新元素y将没有事件侦听器。这可能不是您想要的。


因此,解决此问题的方法是使用本机DOM方法:


for (var i = 0; i < x.childNodes.length; i++) {

    y.appendChild(x.childNodes[i].cloneNode(true));

}

阅读MDN文档可能会有助于理解这种处理方式:


appendChild

cloneNode

childNodes

现在,此问题(如上面的代码示例中的选项2一样)的问题是,它非常冗长,比该innerHTML选项要长得多。当您欣赏拥有一个为您执行此类操作的JavaScript库时。例如,在jQuery中:


$('#y').html($('#x').clone(true, true).contents());

这对您想要发生的事情更为明确。例如,除了具有各种性能优势和保留事件处理程序外,它还可以帮助您了解代码在做什么。这对于您作为JavaScript程序员的灵魂来说是一件好事,并且使异常错误的可能性大大降低!


查看完整回答
反对 回复 2019-11-28
  • 3 回答
  • 0 关注
  • 650 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信