在我们平常工作或学习编写JS代码的过程中,经常会做的一件事就是给某个元素绑定事件。例如鼠标点击,移入,移出等等,以响应用户的某种行为,举个栗子:
上述的栗子是当用户点击某个按钮时会弹出对话框显示”hello world” 。但是在某些情况下,我们期望页面上的一些元素响应用户同样的动作,举个例子。在用户点击列表的每一项时,将其内容显示在div里。例如这样:
用JQuery我们可以这么做:
其实就是给列表的每一项(100个)分别绑定了点击事件。这样做的弊端在于,增加了内存,因为\$(.list li)里有100个li对象。同时降低了代码性能,因为$(’.list li’)会搜索ul下所有的li元素。
那么有没有更好的方法呢?
当然有,那就是事件委托!上面代码也可以这样写:
基本概念
- 什么是事件委托
事件委托又称事件代理(话说之前我以为这两个是不一样的概念…),用网上很经典的一个场景来描述就是取快递:
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
这里其实还有2层意思的:
第一,现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;
第二,新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。
事件委托的原理
事件委托其实就是利用的事件冒泡的原理,而事件冒泡就是事件开始时由最具体的元素(文档中嵌套层次最深的那个节点接收),然后逐级向上传播到最不为具体的节点(文档)。
在本文最开始举例的代码中可以看出:
将li元素的点击事件委托给其父元素ul。这么做之所以行得通,是因为事件具有冒泡的特点,当内层元素的某个事件被触发,事件会一级一级冒泡到更外层元素。当外层元素被绑定事件且被触发时,判断事件的来源即event.target是否是目标元素li,如果是就执行回调。上面的代码等价于:
|
|
- 事件委托的优点
A.使用事件委托可以明显减少dom的操作次数,优化性能和节约内存空间。
B.新添加的元素依然会有之前添加的事件(即新来的员工也能收到快递)。在上例中,如果通过AJAX向列表增加新项,新添加项仍能响应用户点击。在页面动态变化后,不需要重新检索元素和绑定事件。
本文完!
撒花!