在 jQuery 里操作 DOM 时,有个方法经常被新手误解,就是 empty()。很多人以为它是删除元素,实际上它只是把元素内部的子节点和文本内容清干净,元素本身还留在页面上。
这篇文章聊聊 empty() 到底怎么用,以及它跟 remove()、detach() 的区别,顺带分享些我在项目里踩过的坑。
empty() 方法的基本概念
empty() 的作用很纯粹——把选中元素内部的所有东西清空,包括子元素、文本节点、换行符,统统干掉。元素自身的标签、属性、绑定的事件都还在。
语法很简单:
$(selector).empty();
比如你有个 div,里面装了文字、图片、嵌套的 p 标签,执行 $("div").empty() 之后,div 还是那个 div,但里面空空如也。
empty()、remove()、detach() 三兄弟的区别
这三个方法经常被放一起比较,搞清楚了就不会用错。
empty() 像把抽屉里的东西全倒掉,抽屉还在。remove() 直接把抽屉砸了,连抽屉本身带里面的东西全没,绑定的事件和数据也一并清除。detach() 比较特殊,它把抽屉拆下来保存好,上面的事件和数据都保留着,以后还能装回去。
什么时候用哪个?我有个习惯:只是想清空容器重新填充内容,就用 empty();确定这个元素以后再也不需要了,用 remove() 彻底清理;如果可能会把元素移动位置或者暂存起来后面再用,选 detach()。
动手试试:empty() 实战示例
示例一:点击按钮清空指定区域
这个场景很常见,比如表单提交后清空预览区、切换 tab 时清空内容面板。
<!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(){
$("#poemBox").empty();
});
});
</script>
</head>
<body>
<div id="poemBox" style="height:150px; background-color:#f5f5dc; padding:10px;">
代码号学习编程,<br/>
一行一行敲出梦想。</br>
调试排错虽辛苦,<br/>
运行成功心花放。<br/>
<p><b>这段文字会被 empty() 清空。</b></p>
</div>
<p>这个 p 标签在 div 外面,不受影响。</p>
<button>点击清空 div 内容</button>
</body>
</html>
点击按钮后,#poemBox 里的诗句和那个加粗的 p 标签全没了,但 div 本身还在,黄颜色背景照常显示。外面那个 p 标签不受任何影响——因为选择器只选中了 div。
示例二:点击元素自身清空自己
更直观的感受,自己点自己,内容消失:
<!DOCTYPE html>
<html>
<head>
<title>empty() 方法演示</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$(document).ready(function() {
$(".codeBox").click(function () {
$(this).empty();
});
});
</script>
<style>
.codeBox {
margin: 10px;
padding: 12px;
border: 2px solid #555;
width: 80px;
cursor: pointer;
text-align: center;
}
</style>
</head>
<body>
<p>点击下方任意方块,观察 empty() 的效果:</p>
<div class="codeBox" style="background-color:#ffe4b5;">代码号001</div>
<div class="codeBox" style="background-color:#90ee90;">代码号002</div>
<div class="codeBox" style="background-color:#ffb6c1;">代码号003</div>
</body>
</html>
这个例子用了类选择器 .codeBox,三个方块绑定同一个点击事件。点哪个清哪个,其余两个完好。$(this) 指向当前被点击的那个元素,清空的只是它自己内部的内容。边框、背景色这些样式属性保留,因为它们是元素自身的属性,不是子节点。
个人经验:empty() 在 DOM 操作性能上的考量
做过不少单页应用项目,有个感受:当需要频繁更新一个容器里的内容时,用 empty() 比逐个移除子元素要高效。它内部一次性清理所有子节点,减少了浏览器回流次数。
但有个细节得注意——empty() 会移除子元素,这意味着子元素上绑定的事件也会跟着丢失。如果你清空的是整个列表容器,里面每个 li 上用 on() 绑定的事件全没了。所以如果后面还要重新填充类似结构,记得用事件委托绑定到父容器上,而不是直接绑在每个子元素上。
还有个容易被忽略的点:empty() 清除内容时,会释放被移除元素占用的内存吗?jQuery 内部做了清理,移除元素的同时会解除相关的事件绑定和数据引用,帮助垃圾回收。但如果你在其他地方有对被移除元素的 JavaScript 引用,那内存还是放不掉。所以自己写的代码要管理好引用。
empty() 与 innerHTML 的关系
jQuery 的 empty() 底层其实用的是原生 JavaScript 的 innerHTML = '',但它多做了件事:递归遍历所有子元素,逐一清理事件和数据。直接用 innerHTML = '' 速度会更快,但事件和数据可能残留内存。在项目中,如果你没绑定事件和数据,只是清空纯展示内容,两种方式差别不大。但如果用了 $(element).data() 存了东西,还是老老实实用 empty(),让 jQuery 帮你善后。
empty() 用在表单元素上
有个新手容易犯的错——想清空 input 输入框的内容,跑去用 empty()。这没用。input 的值存在 value 属性里,不是子节点。清空 input 的值应该用 val('')。empty() 只对容器型元素有效,比如 div、p、ul、section 这些。
本节课程知识要点
选 empty() 不选 remove() 的场景:你需要保留元素本身,只清内部内容。比如列表刷新、弹窗内容切换、预览区重置,这些情况容器是固定的,变了的是里面的东西,用 empty() 正好。
选 detach() 不选 remove() 的场景:元素要临时移走,之后还会放回来,而且不想丢失绑定的事件和数据。比如拖动排序的列表项、需要缓存的表单组件。
empty() 清空内容后,元素的高度会塌陷,除非你给元素设了固定高度或小高度。做 UI 交互时别忘了处理这点,免得页面布局乱掉。
实际项目里,我通常会在 empty() 之后立即追加新内容,形成"先清空再填充"的模式,保证容器里始终只有新的数据,不会有残留的旧节点捣乱。