首先,让我们定义必须在这里完成的任务:
DIV 的所有子节点x
都必须“复制”(连同其所有后代 = 深复制)并“粘贴”到 DIV 中y
。如果 的任何后代x
绑定了一个或多个事件处理程序,我们可能希望这些处理程序继续处理副本(一旦它们被放置在 中y
)。
现在,这不是一项微不足道的任务。幸运的是,jQuery 库(以及我假设的所有其他流行库)提供了一种方便的方法来完成此任务:.clone()
. 使用这种方法,解决方案可以这样写:
$( x ).contents().clone( true ).appendTo( y );
上述解决方案是问题(2)的答案。现在,让我们解决问题(1):
这
y.innerHTML = x.innerHTML;
不仅仅是一个坏主意——这是一个糟糕的主意。让我解释...
上面的语句可以分为两个步骤。
表达式x.innerHTML
被评估,
该表达式(它是一个字符串)的返回值被分配给y.innerHTML
.
我们要复制的节点(的子节点x
)是 DOM 节点。它们是存在于浏览器内存中的对象。在评估 时x.innerHTML
,浏览器将这些 DOM 节点序列化(字符串化)为一个字符串(HTML 源代码字符串)。
现在,如果我们需要这样一个字符串(例如将其存储在数据库中),那么这种序列化就可以理解了。但是,我们不需要这样的字符串(至少不是作为最终产品)。
在第 2 步中,我们将此字符串分配给y.innerHTML
。浏览器通过解析产生一组 DOM 节点的字符串来评估这一点,然后将这些 DOM 节点插入 DIV y
(作为子节点)。
所以,总结一下:
子节点x
-->字符串化--> HTML 源代码字符串 -->解析--> 节点(副本)
那么,这种方法有什么问题呢?好吧,DOM 节点可能包含不能也因此不会被序列化的属性和功能。最重要的此类功能是绑定到后代的事件处理程序x
- 这些元素的副本不会绑定任何事件处理程序。处理程序在此过程中迷失了方向。
这里可以做一个有趣的类比:
数字信号 --> D/A 转换 --> 模拟信号 --> A/D 转换 --> 数字信号
您可能知道,生成的数字信号并不是原始数字信号的精确副本——一些信息在此过程中丢失了。
我希望你现在明白为什么y.innerHTML = x.innerHTML
应该避免。