← jQuery empty()方法:清空元素 jQuery scrollTop()方法:控制垂直滚动条位置 →

jQuery detach()方法:移除元素但保留数据与事件

原创 2026-04-30 jQuery 已有人查阅

上回聊了 empty() 只是清空元素内部的内容,这次说说它的兄弟 detach()。这个方法做的事更彻底——把整个元素从 DOM 树上摘下来,包括里面的文本和子节点全带走,但元素身上绑定的数据和事件却完好保留着。

detach() 的核心价值就一句话:先拆下来保存着,需要的时候还能原样装回去。跟搬家具似的,桌子拆了搬走,抽屉里的东西跟着走,桌面上贴的便签也不会掉。

detach() 方法的语法

写法很简单:

$(selector).detach();

执行后,选中的元素从页面消失,但返回的 jQuery 对象里保存着这个元素,你可以把它存到变量里,后面随时追加回 DOM 的任何位置。

detach()、remove()、empty() 三者到底差在哪

这三个方法摆在一起才容易看出区别。

empty() 前面讲过了,只清空元素内部的东西,元素本身纹丝不动,身上的事件和数据也在。

remove() 是斩草除根型,元素本身、内部内容、绑定的事件、存的数据全删干净。适合那种"这个元素再也不会出现了"的场景。

detach() 介于两者之间——元素和内容从页面上移除,但事件和数据原封不动保存在返回的 jQuery 对象里。等你把元素重新插回页面,之前绑的点击事件照样能触发,存的数据照样能读到。

我之前有个项目需要做列表项的跨面板拖拽,一开始用 remove() 移除后再新建元素插回去,结果发现之前绑的编辑事件全丢了,得重新绑一遍,代码绕来绕去。后来换成 detach(),元素移过去直接 appendTo,事件保留,省了一大段重复绑定逻辑。这就是为什么在需要"暂存并复用元素"的场景下,选 detach() 而不是 remove()

动手感受:detach() 基础示例

先看个简单的,点击按钮把所有 p 标签拆走:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
    $("button").click(function(){
        $("p").detach();
    });
});
</script>
</head>
<body>
<p>代码号学习编程第一行</p>
<p>代码号学习编程第二行</p>
<button>点击移走所有 p 元素</button>
</body>
</html>

点击按钮后两段文字从页面消失,但 jQuery 在后台保留着它们。只是这个例子没存引用,摘下来就真丢了。实际项目里记得用变量接住。

进阶玩法:把 detach() 下来的元素装回去

这个例子展示了 detach() 的真正用法——临时移除,稍后恢复:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>detach() 方法演示</title>
<style>
p {
    background: #ffd1dc;
    margin: 6px 0;
    padding: 6px;
    cursor: pointer;
}
</style>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<p>代码号编程笔记第一条</p>
<p>代码号编程笔记第二条</p>
<button>切换段落显示/隐藏</button>

<script>
// 给段落绑定点击事件
$("p").click(function() {
    $(this).toggleClass("off");
});

var savedParagraphs;
$("button").click(function() {
    if (savedParagraphs) {
        // 变量里有存着的元素,装回 body
        savedParagraphs.appendTo("body");
        savedParagraphs = null;
    } else {
        // 没存着,拆下来保存
        savedParagraphs = $("p").detach();
    }
});
</script>
</body>
</html>

这段代码的精妙之处:先用 detach() 把所有 p 移走并存入变量 savedParagraphs,下次点击按钮发现变量里有东西,就用 appendTo("body") 把它们装回去。装回去的段落之前绑定的点击事件(切换 class)依然有效。如果换成 remove(),装回去的就得重新绑定事件。

关键对决:detach() 和 remove() 的行为差异

下面这个例子能直观感受两者区别,同一个页面,左边用 detach() 移动元素,右边用 remove() 移动元素:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
    // 给所有 p 绑定点击变大字号的事件
    $("p").click(function(){
        $(this).animate({fontSize: "+=1px"});
    });

    $("#btnDetach").click(function(){
        $("body").append($("#paraDetach").detach());
    });

    $("#btnRemove").click(function(){
        $("body").append($("#paraRemove").remove());
    });
});
</script>
<style>
p { cursor: pointer; margin: 8px 0; }
</style>
</head>
<body>
<p id="paraDetach"><b>代码号之detach:移走再放回,点击事件还在。</b></p>
<p id="paraRemove">代码号之remove:移走再放回,点击事件丢失。</p>
<button id="btnDetach">detach 并追加到 body 末尾</button>
<button id="btnRemove">remove 并追加到 body 末尾</button>
</body>
</html>

两个段落都绑定了点击逐级放大字号的事件。分别点击两个按钮后,段落被移到 body 底部。

再去点击移回来的段落,第一条(用 detach() 处理的)字号依然会变大,事件完好。第二条(用 remove() 处理的)点上去没反应——事件已经被 remove() 一并清掉了。

这个对比把两种方法的本质差异展示得明明白白。detach() 保留的不仅是元素结构,还有整个 jQuery 事件体系以及通过 $(element).data() 存储的自定义数据。

detach() 在复培育互中的实战价值

分享下个人在项目中的使用心得。做代码号在线编程平台的交互编辑器时,有个功能是把组件面板里的代码片段拖到工作区。用户可能会把组件拖进拖出好几次来调整布局。

一开始用了 remove() 的方案,每次拖出就删掉重新创建 DOM 结构去。结果发现组件上的状态(比如用户设置的参数、展开折叠状态)全没了,每次都要重新从配置读数据重新渲染,性能差代码也乱。

后面改用 detach(),从面板拖出时把元素 detach 出来存着,放入工作区时直接 appendTo 到目标容器。组件上所有状态原封不动,绑定的事件一个不差。代码直接少了一个"状态恢复"模块。

这也引出一个经验:如果你的元素上有通过 $(selector).on('click', handler) 绑定的直接事件,或者用 $(selector).data('key', value) 存了业务数据,并且在 DOM 移动的过程中这些东西需要保留,那就选 detach()。如果元素要被彻底销毁换新的,选 remove(),让 jQuery 帮你把关联的事件和数据清理干净,防止内存泄漏。

关于性能的一点补充

detach() 操作时 jQuery 需要遍历元素及其所有子元素,把事件和数据提取保存。元素层级很深、子节点很多时,这个遍历有一定开销。但比起销毁后重建整个 DOM 树并重新绑定事件,这点开销通常还是划算的。具体选型取决于你的场景——是移动次数频繁还是元素结构特别庞大。

本节课程知识要点

用 detach() 而不用 remove() 的决策依据:你需要把元素从当前位置移到别处,并且希望元素上的事件处理函数、用 data() 存储的自定义数据继续保持有效。典型场景包括拖拽排序、面板切换暂存、列表项的跨容器迁移。

用 empty() 而不用 detach() 的场景:元素本身要留在页面上继续用,只是内部内容需要清空刷新。比如分页列表刷新时清空 tbody、切换 tab 时清空内容面板。

把 detach() 拆下来的元素装回去,常用 appendTo()prependTo()insertAfter()insertBefore() 这些 DOM 插入方法,选哪个取决于你希望元素出现在什么位置。

拆下来别忘了存变量里,不然拿不回来。如果在 detach 之后做了其他操作导致变量被覆盖,元素就真的找不回来了——虽然还能在内存里被垃圾回收,不算泄漏,但功能上等于白干。

← jQuery empty()方法:清空元素 jQuery scrollTop()方法:控制垂直滚动条位置 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号