DOM 修改:切除、移植与再造


文档摘要

3.4 DOM 修改:切除、移植与再造 别把修改 DOM 想成字符串拼接——直接拼 HTML 字符串再整体刷新,会把已经绑好的事件、挂在元素上的数据全部冲掉。正确的思路是把文档当成活体组织:新增的组织往哪个切口放进去、既有组织怎么整体移植、坏死部分如何切除,各有专门的术式。本节是本章的收官动作,也是第 6 章"AJAX 拿到数据往页面上放"的全部技术储备。 本节摘要:插入按方位分四刀: 与 进容器内部首尾, 与 贴在目标外侧前后;移植用 或组合 与 ;再造靠 (传真保留事件)与 ;切除三刀 、 、 按是否保留数据与事件区分。 插入四向:切口决定术式 四刀的分工看两个坐标:相对容器还是相对兄弟,在内部还是在外侧。记不清时用一句话校准——append 系找容器,after 系找邻居。

3.4 DOM 修改:切除、移植与再造

别把修改 DOM 想成字符串拼接——直接拼 HTML 字符串再整体刷新,会把已经绑好的事件、挂在元素上的数据全部冲掉。正确的思路是把文档当成活体组织:新增的组织往哪个切口放进去、既有组织怎么整体移植、坏死部分如何切除,各有专门的术式。本节是本章的收官动作,也是第 6 章"AJAX 拿到数据往页面上放"的全部技术储备。

本节摘要:插入按方位分四刀:appendprepend 进容器内部首尾,afterbefore 贴在目标外侧前后;移植用 appendTo 或组合 detachappend;再造靠 clone(传真保留事件)与 wrap;切除三刀 removedetachempty 按是否保留数据与事件区分。

插入四向:切口决定术式

// 容器内部:末尾追加 / 开头插入 $('#queue').append('<li class="item">新挂号 · 孙七</li>'); $('#queue').prepend('<li class="item">加急插队 · 周八</li>'); // 目标外侧:身后贴一个 / 身前贴一个 $('.urgent').after('<li class="note">候补一人</li>'); $('.urgent').before('<div class="divider">以下为急症</div>');

四刀的分工看两个坐标:相对容器还是相对兄弟,在内部还是在外侧。记不清时用一句话校准——append 系找容器,after 系找邻居。配套的主动语态版本 appendTo 适合链式场景:

$('<li class="item">新挂号 · 孙七</li>') .addClass('fresh') .appendTo('#queue'); // 先造好、穿好、再送进容器

移植与再造:clone、wrap 与内容替换

既有元素搬家不需要拆了重建——把 jQuery 对象直接 append 进新容器,它会从原位置移动过去(文档里同一个节点只能有一个位置):

$('.urgent').appendTo('#done-list'); // 整体移植,事件与数据随行

需要"复制一份"时才请出 clone,参数决定手术质量:

var copy = $('.urgent').clone(); // 浅克隆:只有结构样式 var full = $('.urgent').clone(true); // 深克隆:连事件处理器一起复制

clone(true) 传真这个细节请先记住,它的意义要到第 4 章讲完事件绑定才能体会——没传真就搬家的元素,一到新地方就"点不动",是排错榜上的常客。外围手术还有 wrap(给目标套一层容器)与 replaceWith(以新换旧),按需查阅即可。

内容层面的批量替换走 htmltexthtml() 读写内部 HTML,text() 只碰纯文本。它们常被误用于高频刷新——每次 html() 都重新解析字符串并扔掉旧节点,频繁调用代价不小。

切除三刀:remove、detach、empty

$('.done').remove(); // 摘除并销毁:数据与事件一并清除 $('.done').detach(); // 摘除但保留:还能原样接回 $('#queue').empty(); // 清空容器内部:容器自己留下

三刀的差别全在"切下来之后还认不认账"。remove 是彻底切除;detach 是暂存待回植——场景如"筛选期间先把不合条件的人摘出去,恢复时再接回来";empty 动的是容器内部,容器本身毫发无损。选错刀的典型症状是:用 remove 摘下来的元素接回去之后事件失灵——因为数据账和事件账在切除时已被销毁。

图:四向插入与切除三刀示意

图:四向插入与切除三刀示意

完整案例:叫号后的条目流转

背景:分诊台叫到号后,该条目要从候诊队列移到"已完成"列表,并允许误操作撤销。操作、结果、解读、变式一次走完:

// 候诊与完成两个容器 var $queue = $('#queue'); var $done = $('#done-list'); // 叫号:找到队首,摘下(保留数据与事件),接进完成列表 function callNext() { var $first = $queue.children('.item').first(); if ($first.length === 0) { console.warn('队列已空'); return; } $first.removeClass('urgent stable').addClass('done'); $first.detach().appendTo($done); // detach 后接回,事件账未动 } // 撤销:从完成列表摘下最后一位,送回候诊队列开头 function undoLast() { var $last = $done.children('.item').last(); $last.detach().prependTo($queue); }

结果:条目在两个列表之间往返,类名随状态切换,绑在条目上的点击事件始终有效。解读:如果用的是 remove,第二次 callNext 之前接回的条目会变成"事件死体";detach 保住了整本账,流转才成立。变式:要求撤销时恢复原类名,就在摘下前先 data('prevClass', this.className) 存档、接回时还原——data 账本在这里恰好派上用场,呼应上一节。

原生对照:四向与三刀的本来面目

jQuery 原生 备注
$box.append(html) box.insertAdjacentHTML('beforeend', html) 或先 createElementappendChild 原生 append 只收节点不收字符串
$el.after(x) el.insertAdjacentElement('afterend', x) 现代原生已有 afterbefore
$el.remove() el.remove() 同名同义,已是标准
$el.replaceWith(x) el.replaceWith(x) 同名同义
$el.detach() 无对应 原生靠先摘下引用变通保留
$el.clone(true) el.cloneNode(true) cloneNode 不复制事件监听

注意最后一行:原生克隆从不带走监听器,jQuery 的 clone(true) 是类库自己记账才做到的——这是"事件账本存在类库里"的第一个信号,下一章就翻开这本账。

要点复盘

  • 插入四向按坐标选刀:append 系找容器(内部首尾),after 系找邻居(外侧前后)。
  • 移植直接 append 进新容器即可;要复制才有 clone,且传真参数决定事件是否随行。
  • 切除三刀按"还认不认账"区分:remove 销毁、detach 暂存、empty 清壳。
  • 高频刷新别滥用 html(),每次解析字符串都是重新施工。
  • 原生 afterremovereplaceWith 已成标准,简单场景可以直接迁移;detach 与带事件克隆是 jQuery 的独门账本。

结构手术到此出师。下一章给这台手术台接神经:让页面听得懂点击、输入与提交。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U