简述JS中的event delegate


简述JS中的event delegate(事件委托)
分享人:杨亚洲
目录
1 .背景介绍
2.知识剖析
3.常见问题
4.解决方案
5 .编码实战
6.扩展思考
7.参考文献
8.更多讨论
1.背景介绍
浏览器获取事件的两种方式:事件冒泡和事件捕获
事件冒泡:先触发子元素的事件,再触发父元素的事件
事件捕获:先触发父元素的事件,再触发子元素的事件
主流浏览器均支持且优先使用事件冒泡机制
简单的捕获机制
那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,
就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了,
举个例子:
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;
二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案
(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,
然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,
那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
这里其实还有2层意思的:
第一,现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;
第二,新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。
2.知识剖析
    为什么要用事件委托:
     一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,
那如果是很多的dom需要添加事件处理呢?比如我们有100个li,
每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,
然后给它们添加事件,那这么做会存在什么影响呢?
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,
因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,
就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;
如果要用事件委托就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大
                            的减少与dom的交互次数,提高性能
每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,
自然性能就越差了(内存不够用,是硬伤,哈哈),比如上面的100个li,就要占用100个内存空间,
如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级
(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,
                            自然性能就会更好。
(demo2)
利用事件会冒泡的属性,委托它们父级代为执行事件。(demo3)
3.常见问题
事件委托中,只想触发特定元素的事件怎么办?
Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,
                    target就可以表示为当前的事件操作的dom,
那么如果是新增的节点,新增的节点会有事件吗?一个新员工来了,他能收到快递吗?
是可以的(demo4)
4.解决方案
事件委托解决的问题:
(1-可以绑定文档完成后新出现的子元素)
(2-指定绑定事件的范围(父元素))
3-不需要为每个元素设置绑定
5.编码实战:
6.扩展思考
如何在jquery中使用事件委托?
on方法(demo5)
如何清除事件委托
对于jq来说,如需移除事件处理程序, 请使用 off()方法。如需添加只运行一次的事件然后移除,
请使用 one() 方法
7.参考文献

        
8.更多讨论
事件委托的缺点
1、事件委托基于冒泡,对于不冒泡的事件不支持。(demo6)
load,unload,blur,fouse,mouseenter,mouseleave

2、 层级过多,冒泡过程中,可能会被某层阻止掉。(demo7)


3、理论上委托会导致浏览器频繁调用处理函数,
虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。


        三个问题

                1、如何在jquery中使用事件委托?

                   on方法的语法  

                    $(selector).on(event,childSelector,function(){})        

                    on方法语法,绑定在父元素上 事件,子选择器,回调函数

                2、事件委托中,只想触发特定元素的事件怎么办?

Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,
                    target就可以表示为当前的事件操作的dom,
那么如果是新增的节点,新增的节点会有事件吗?一个新员工来了,他能收到快递吗?
是可以的(demo4)
                    3、事件委托解决的问题:

a-可以绑定文档完成后新出现的子元素
b-指定绑定事件的范围(父元素)
c-不需要为每个元素设置绑定


    







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
public enum EventType { None, ButtonPress, KeyPress, MouseClick } public class EventManager : MonoBehaviour { public delegate void EventDelegate(EventType eventType); private Dictionary<EventType, EventDelegate> eventDictionary; private static EventManager eventManager; public static EventManager instance { get { if (!eventManager) { eventManager = FindObjectOfType(typeof(EventManager)) as EventManager; if (!eventManager) { Debug.LogError("There needs to be one active EventManager script on a GameObject in your scene."); } else { eventManager.Init(); } } return eventManager; } } void Init() { if (eventDictionary == null) { eventDictionary = new Dictionary<EventType, EventDelegate>(); } } public static void StartListening(EventType eventType, EventDelegate listener) { EventDelegate thisEvent; if (instance.eventDictionary.TryGetValue(eventType, out thisEvent)) { thisEvent += listener; instance.eventDictionary[eventType] = thisEvent; } else { thisEvent += listener; instance.eventDictionary.Add(eventType, thisEvent); } } public static void StopListening(EventType eventType, EventDelegate listener) { if (eventManager == null) return; EventDelegate thisEvent; if (instance.eventDictionary.TryGetValue(eventType, out thisEvent)) { thisEvent -= listener; instance.eventDictionary[eventType] = thisEvent; } } public static void TriggerEvent(EventType eventType) { EventDelegate thisEvent = null; if (instance.eventDictionary.TryGetValue(eventType, out thisEvent)) { thisEvent.Invoke(eventType); } } }添加注释
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值