前面讲事件绑定的时候反复提到一个概念——动态添加的元素无法用 click() 或 bind() 直接绑定事件,需要用事件委托来解决。delegate() 就是 jQuery 专门用来做事件委托的方法之一。
它的工作方式是:把事件处理器绑定在一个已经存在的父元素上,然后指定一个子元素选择器。当父元素上发生指定事件时,jQuery 会检查事件的实际触发目标是否匹配子元素选择器,匹配的话就执行回调函数。这样一来,即便是后来才动态添加到页面上的子元素,只要它能被选择器匹配到,事件处理就能生效。
不过和 bind() 的命运类似,delegate() 从 jQuery 1.7 开始也被 on() 方法所取代。现在官方推荐统一用 on() 来处理事件委托。但理解 delegate() 的用法和原理,对于维护老代码以及理解 on() 的委托语法都很有帮助。
语法形式
$(selector).delegate(childSelector, event, data, function)
childSelector(必填): 一个选择器字符串,用于指定哪些子元素可以触发事件处理函数。只有匹配这个选择器的元素才会响应事件。
event(必填): 要绑定的事件类型,多个事件用空格分隔,如 "click"、"mouseenter mouseleave"。
data(可选): 传递给事件处理函数的额外数据。
function(必填): 事件触发时执行的回调函数。回调中的 $(this) 指向匹配 childSelector 的那个子元素,而不是父元素。
基础示例:点击段落动态生成新段落
下面这个例子展示了 delegate() 的核心用法。在 body 上委托处理 p 元素的 click 事件,每次点击段落都会在它后面追加一个新段落。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>delegate() 基础示例</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<style>
p {
background: #f9e79f;
font-weight: bold;
cursor: pointer;
padding: 8px;
margin: 4px 0;
}
p.over {
background: #ccc;
}
.info {
color: #c0392b;
}
</style>
</head>
<body>
<p>点击我生成新的段落</p>
<div class="info" style="margin-top:10px;"></div>
<script>
$("body").delegate("p", "click", function(){
$(this).after("<p>新生成的段落,点击我也能继续生成</p>");
});
</script>
</body>
</html>
点击第一个黄颜色段落,它下面会新增一个段落。再点击这个新生成的段落,它同样能触发点击事件继续生成。这就是事件委托的核心优势——新添加的 p 元素在绑定事件时还不存在于 DOM 中,但因为事件处理器挂在 body 上,新元素自动继承了父元素的事件处理逻辑。
delegate 的工作原理
理解 delegate() 的运作机制对用好事件委托很重要。它的工作流程分三步:
-
把事件处理器绑定在父元素上(比如
body)。 -
当父元素内部任意位置发生指定事件时,事件会沿着 DOM 树冒泡到父元素。
-
jQuery 检查事件的实际触发目标是否匹配
childSelector。匹配就执行回调,不匹配就忽略。
这套机制依赖事件冒泡。之前讲过的 mouseenter 和 mouseleave 不冒泡,所以 delegate() 对这两个事件无效。需要用事件委托时记得选会冒泡的事件类型,比如 click、mouseover、keydown 等。
delegate 和 on 的对应关系
delegate() 和 on() 之间的转换很简单,把参数的位置调整一下就行:
// delegate 写法:父元素上委托子元素
$("body").delegate("p", "click", function(){
// 处理逻辑
});
// on 写法:效果一样
$("body").on("click", "p", function(){
// 处理逻辑
});
注意两个方法的参数顺序不同。delegate() 是 childSelector 在前、event 在后;on() 反过来,event 在前、childSelector 在后。这个差异是迁移代码时比较容易写错的地方。
delegate 的实际应用场景
事件委托在这些场景中特别有用:
-
动态列表管理: 待办事项列表里,用户新增的每一项都需要支持删除、完成等操作,不可能每新增一项都重新绑定事件。
-
表格行交互: 表格数据由 AJAX 动态加载,行数随时变化,点击行高亮、删除按钮等操作适合用委托。
-
评论区回复: 用户发表的新评论需要支持点赞、回复等操作,委托机制让这些动态内容自动具备交互能力。
-
无限滚动列表: 随着滚动自动加载更多内容,新加载的内容也需要响应点击等操作。
本节课程知识要点
-
delegate()用于在父元素上绑定事件处理器,由匹配childSelector的子元素来触发回调。 -
支持对动态添加的子元素生效,因为事件处理器挂在父元素上而非子元素本身。
-
依赖事件冒泡机制,不会冒泡的事件(如
mouseenter、mouseleave)无法使用delegate()。 -
从 jQuery 1.7 起被
on()方法取代,迁移时将delegate(childSelector, event, fn)改为on(event, childSelector, fn)。 -
回调中的
$(this)指向触发事件的子元素,不是父元素,方便直接操作子元素。
delegate() 是 jQuery 事件委托机制演进中的一个重要方法。它解决了动态元素事件绑定的痛点,让代码在面对频繁的 DOM 增删操作时仍然保持简洁稳定。虽然现在统一用 on() 来替代它,但理解 delegate() 的参数结构和委托原理,能帮助更好地理解 on() 的委托语法以及事件冒泡在 jQuery 中的实际应用。事件委托是 jQuery 事件体系里比较实用的技巧之一,用好了能让交互代码的维护成本降低不少。