jQuery 的 clone 创建节点副本,after、append 等方法再决定把副本放在哪里。复制与插入是两个步骤,不是把原节点移动过去。
clone(true) 中 true 的含义
一个常见写法是:
var source = $("#sourceBlock");
var copy = source.clone(true);
source.after(copy);
clone 会复制节点树。true 进一步涉及绑定在元素上的 jQuery 事件和数据,并不是把所有相关 JavaScript 对象做一次深拷贝。
例如,data 中保存的对象或数组可能仍共享引用;修改副本中的嵌套数据,也可能影响原节点读取到的数据。jQuery clone
复制之前先解决身份
上面的简短片段会连 sourceBlock 这个 id 一起复制,直接插入会产生重复 ID。如果后代还有 id,label 的 for、ARIA 引用或脚本选择器也可能受影响。
要么逐一重新生成标识并更新关联属性,要么在可重复结构里使用不依赖全局 ID 的设计。只改最外层 id 不足以处理整个子树。
无 ID 行的明确示例
假设只复制下面这类普通文本输入行,并且新增行应为空:
<div class="rows">
<div class="repeatable-row">
<label>名称 <input name="itemName" type="text"></label>
</div>
</div>
在 DOM 就绪、已有 jQuery 的环境中:
var rows = $(".rows").first();
var source = rows.children(".repeatable-row").first();
if (source.length) {
var copy = source.clone(false);
copy.find("input[type='text']").val("");
rows.append(copy);
}
label 包裹输入框,不依赖复制后的重复 for/id。这里明确重置文本值,不把它扩展为文件上传、富文本编辑器或任意插件的通用复制器。
不复制直接事件,也可能有委托行为
clone(false) 不复制原节点直接绑定的 jQuery 事件和数据,但稳定祖先上的事件委托仍可能处理新节点。初始化副本时,应避免又手工绑定一次相同事件。
表单控件的动态状态也不保证都按同样方式复制:文本、选择项、textarea 和插件内部模型应分别确认。决定新行是“复制现有记录”还是“创建空白记录”,再按字段规则设置状态,比依赖 clone 的偶然结果更可靠。