今天在公司,有个需求是,通过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()方法绑定事件处理程序到当前选定的jQuery对象中的元素。在jQuery 1.7中,.on()方法 提供绑定事件处理程序所需的所有功能。帮助从旧的jQuery事件方法转换,see .bind(), .delegate(), 和 .live(). 要删除的.on()绑定的事件,请参阅.off()。要附加一个事件,只运行一次,然后删除自己, 请参阅.one()
events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" 。
selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。如果选择的< null或省略,当它到达选定的元素,事件总是触发。
data:当一个事件被触发时要传递event.data给事件处理函数。
fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。
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。是的话触发对应的事件,从而 达到事件的委托。