今天在公司,有个需求是,通过ajax动态查询数据,回来,再添加到一个ul的li元素中,例如(点击生成 li 模拟,加载数据生成相应的数据, 事件: 点击):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<button>create</button>
<ul id="parent">
<li class="son-1">Item 1</li>
<li class="son-2">Item 2</li>
</ul>
<script>
$(function () {
$('button').on('click', function (e) {
$('#parent').append('<li>add</li>')
});
});
</script>
</body>
</html>
平时自己的添加事件:
$('#parent li').on('click', function (e) {
alert('这是第' + $(this).index() + 'li');
});
这样子可以为,dom元素中已经经过渲染的li元素绑定事件,如果点击 craete按钮新生成的li元素,由于,事件绑定的js已经执行完毕,所以无法对新生成的li进行事件的绑定。一开始,在没有用jq的事件委托,自己简单的粗暴的对新生的元素,再一次动态绑定:
//在生成新生元素后, 再次执行这段 函数 ,绑定需要的事件。
$('#parent li').on('click', function (e) {
alert('这是第' + $(this).index() + 'li');
});
明显是很挫的做法,不仅不易维护,而且性能也大打折扣,因为这样虽然会为新的元素绑定到事件,但是已经存在的元素也会再次绑。
jq提供的事件委托,可以很有效的解决这种问题。delegate 和 on 都提供了相应的方法
$('#parent').delegate('li', 'click', function(event) {
console.log($(this))
});
$('#parent').on('click', 'li', function (e) {
console.log($(this))
});
这两个函数均可提供相应的效果,个人更倾向于使用 on :
下面是从jq的api copy过来的使用文档:
on(events,[selector],[data],fn)
概述
在选择元素上绑定一个或多个事件的事件处理函数。
on()方法绑定事件处理程序到当前选定的jQuery对象中的元素。在jQuery 1.7中,.on()方法 提供绑定事件处理程序所需的所有功能。帮助从旧的jQuery事件方法转换,see .bind(), .delegate(), 和 .live(). 要删除的.on()绑定的事件,请参阅.off()。要附加一个事件,只运行一次,然后删除自己, 请参阅.one()
参数
events,[selector],[data],fnV1.7
events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" 。
selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。如果选择的< null或省略,当它到达选定的元素,事件总是触发。
data:当一个事件被触发时要传递event.data给事件处理函数。
fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。
events-map,[selector],[data]V1.7
events-map:个用字符串表示的,一个或多个空格分隔的事件类型和可选的命名空间,值表示事件绑定的处理函数。
selector:一个选择器字符串过滤选定的元素,该选择器的后裔元素将调用处理程序。如果选择是空或被忽略,当它到达选定的元素,事件总是触发。
data:当一个事件被触发时要传递event.data给事件处理函数。
javascript也有原生的事件委托
DEMO:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" id="btn" />
<ul id="ul">
<li>aaaaaaaa</li>
<li>bbbbbbbb</li>
<li>cccccccc</li>
</ul>
<script>
window.onload = function(){
var oUl = document.getElementById("ul");
var aLi = oUl.getElementsByTagName("li");
var oBtn = document.getElementById("btn");
var iNow = 4;
oUl.onmouseover = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == "li"){
alert('触发了')
}
}
oUl.onmouseout = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == "li"){
alert('触发了')
}
}
oBtn.onclick = function(){
iNow ++;
var oLi = document.createElement("li");
oLi.innerHTML = iNow;
oUl.appendChild(oLi);
}
}
</script>
</body>
</html>
从原生的js中可以看出:事件委托是通过,事件的冒泡。实现的。通过子元素的点击事件,冒泡到父元素,父元素再通过event的内容判断 为该元素触发相应的事件, 在demo中的,获取对应的 tagName 判断子元素 是不是 li。是的话触发对应的事件,从而 达到事件的委托。