学习jQuery事件时遇到一个问题。如下:
简单设置一个表格
<div>
<table>
<tbody>
<tr>
<td>上海</td>
<td>北京</td>
<td>深圳</td>
<td>
<button type="button" name="del">删除</button>
</td>
</tr>
<tr>
<td>吃饭</td>
<td>睡觉</td>
<td>上网</td>
<td>
<button type="button" name="del">删除</button>
</td>
</tr>
</tbody>
</table>
</div>
<button type="button" id="add">添加</button>
展示如下图:
为其简单设置两个点击事件:当点击删除时,会删除当前行,点击添加时,会添加一行
<script>
//添加
$('#add').click(function () {
$('tbody').append('<tr><td>嘻嘻</td><td>哈哈</td><td>嘿嘿</td><td><button type="button" name="del">删除</button></td></tr>')
});
//删除
$('button[name="del"]').click(function () {
$(this).parent().parent().remove();
})
</script>
发现可以达到想要的效果。
但是又发现出现一个问题,当点击添加添加了新的一行时,点击新的一行的“删除”按钮,并不能删除这一行。
查询相关内容得知,主要是因为没有进行事件的动态绑定。
我们将jQuery事件进行绑定时主要有以下4种方式
1、live()方法
该方法已经过时,不用。
2、bind()方法
该方法本质上就是我们所使用的方法:
$('button[name="del"]').click(function () {
$(this).parent().parent().remove();
})
其实这是该方法的简写形式,省略了bind(),其完整形式如下:
$('button[name="del"]').bind('click',function () {
$(this).parent().parent().remove();
})
该方法可以直接将指定的元素与事件绑定,其有简便快捷的优点。
但是,当要绑定的元素过多,则需一一对应的进行绑定,会损耗大量的性能。并且,该方法不能进行动态绑定,也就是说,对于加载完之后,新增的元素,无法与事件绑定。
3、delegate()方法
这个方法绑定的元素并不是事件对应的元素,而是其父元素或祖先元素。
当发生事件时,事件会从事件发生的元素向上冒泡,直到找到所绑定的父元素或祖先元素,冒泡过程中,若事件的currentTarget和选择器匹配,则会直到。
如,在本例中,当点击button元素时,事件会向上找td或tr或更高级的元素(这个是自己设置的),然后再执行。
代码如下:
$('tbody').delegate('button','click',function () {
$(this).parent().parent().remove();
})
本例中,要找的祖辈元素是:tbody或更高级的元素,因为只有tbody以上的元素才是一直有的元素,可以被找到。
如果写成了tr,因为tr是新增的,则找不到tr,也就无法删除。
也就是说,父辈或祖先辈的元素,一定要写以前有的元素,并且该元素是新增的元素的父辈元素【非常重要!!!】。
甚至可以写成document,即为文档级别的,可以在document准备好之前就执行,如下:
$(document).delegate('button[name="del"]','click',function () {
$(this).parent().parent().remove();
})
要注意:这里的发生事件元素就不能直接写button元素了,因为如果直接写button元素,会将添加按钮和删除按钮都设置删除事件,导致点击添加按钮,也会删除。因为他们都是document文档内的button元素。所以要写成button[name=“del”],找到删除这个元素。
而刚刚可以直接写button的原因,是因为tbody元素下,只有一个button,即删除的button。
使用delegate()方法来添加事件,可以动态的给元素设置事件。 但是,如果说发生事件的元素在DOM树深处,距离查询的父元素或祖辈元素较远,则会损耗更多的时间与性能。
4、on()方法
该方法实际上是bind方法和delegate方法的底层,调用时只需要将事件名types和选择的元素selector参数交换位置即可。
如,本例中,代码如下:
$(document).on('click','button[name="del"]', function () {
$(this).parent().parent().remove();
})
on方法定义为:on( types, selector, data, fn )
types:指的是发生的事件的类型,如点击事件click,鼠标移入事件mouseenter等。
selector:指的是选择的元素,比如div、p等
data:指的是参数
fn:指的是匿名函数
’
bind方法:
function( types, data, fn ) {
return this.on( types, null, data, fn );
},
delegate方法:
delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
}
可以看出bind和delegate方法底层都是on方法。on方法是官方文档中推荐的方法。
最后,总结如下:
方法名 | 优点 | 缺点 |
---|---|---|
bind() | 绑定时简单快捷,用在绑定数量较少的元素时很方便。(如对某个元素进行id绑定) | 1、当绑定数量较多时,效率和性能会降低。2、对于后期动态新增的元素无法进行绑定 |
delegate() | 通过冒泡方式向上查找元素,对于新增的元素可以很好的查询。 | 当事件元素在DOM文档树过深处位置,向上冒泡时会耗费更多时间和性能 |
on() | bind()和delegate() 的底层,官方文档推荐使用。 |