当前位置: 首页 > 面试题库 >

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

卢涵畅
2023-03-14
问题内容

假设我们x在页面上有一个DIV ,并且想要将该DIV的内容复制(“复制粘贴”)到另一个DIV中y。我们可以这样做:

y.innerHTML = x.innerHTML;

或使用jQuery:

$(y).html( $(x).html() );

但是,看来此方法不是一个好主意,应避免使用。

(1)为什么要避免这种方法?

(2)应该怎么做呢?

更新:
为了解决这个问题,我们假设DIV中没有ID为ID的元素x
(对不起,我忘了在原始问题中介绍此案。)

结论:
我已经在下面发布了我对这个问题的答案(如我最初的意图)。现在,我还计划接受自己的答案:P,但是孤独某日的答案是如此惊人,以至于我不得不接受它。


问题答案:

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

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

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

因此,不应将其用于修改现有网页。DOM(文档对象模型)具有用于更改页面内容的系统。这是基于节点的关系,而不是基于HTML序列化。因此,当你添加一个liul,你有这两个选项(假设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程序员的灵魂来说是一件好事,并且使异常错误的可能性大大降低!



 类似资料:
  • 问题内容: 通常我会尽可能避免转换类型,因为我认为这是不良的编码实践,并且可能会导致性能下降。 但是,如果有人要我解释为什么会这样,我可能会像前灯中的鹿一样看它们。 那么,为什么/何时铸造不好? 它对于Java,C#,C ++是通用的,还是每个不同的运行时环境都按照自己的方式处理? 欢迎使用任何语言的细节,例如为什么在c ++中不好? 问题答案: 您已经用三种语言标记了这三种语言,答案在三种语言之

  • 在React中,我尝试了两种方法: 然后更改状态this.setState(this.state) 克隆状态,更改状态克隆,然后更改此.setState(stateClone) 它们都起作用,产生相同的结果。为什么建议(在文档中)设置为状态克隆(使用Object.assign),而不是设置为状态本身?状态的对象标识在React中重要吗(没有Redux)?似乎只要调用setState,不管状态对象标

  • 我的公司不允许使用Mockito。在单元测试中验证。甚至有一个定制的声纳规则 规则如下 应该通过断言来验证结果,而不是使用“验证到执行”过程验证。因为如果我们验证流程,在流程更改后需要更多的努力来维护测试,但输入和输出保持不变。确保每一行代码都对结果有影响,并断言结果以证明逻辑正确 不合规代码示例 合规解决方案 对于数据库或中间件操作,断言使用嵌入式数据库或中间件成功写入数据。 对于restful

  • 问题内容: 我已经在多个地方多次看到过这种情况,但是从未找到令人满意的解释来说明为什么会这样。 因此,希望这里会介绍一个。为什么我们(至少通常)不使用和? 编辑:我看到人们以为这个问题与Web服务器有关,但事实并非如此。我可以理解为什么传递给未经处理的字符串可能很糟糕。在非Web应用程序中不好吗? 问题答案: 通常有更清晰,更直接的方法来获得相同的效果。如果构建复杂的字符串并将其传递给,则代码将难

  • 问题内容: 我知道使用执行程序而不是ThreadGroup的当前做法: 通常首选的处理线程的方法 从线程等捕获异常… 但是,这样 的ThreadGroup 固有的 缺陷是 什么(我听过对该类的模糊批评)? 感谢您的回答。 PS。这似乎无法回答这个问题。 问题答案: 这在《有效的Java第二版》中进行了解释。,项目73。 最初将线程组设想为一种出于安全目的隔离小程序的机制。他们从来没有真正兑现过这个

  • 问题内容: 为什么是选择?如果添加了想要的新列,这是否意味着更少的代码更改? 我知道这在某些数据库上是性能问题,但是如果您真的想要每列,该怎么办? 问题答案: 确实有三个主要原因: 将数据转移到消费者方面效率低下。 当您选择SELECT *时,通常从数据库中检索到的列数超出了应用程序实际需要运行的列数。这将导致更多数据从数据库服务器移至客户端,从而减慢访问速度并增加计算机上的负载,并花费更多时间在