Ruby's Louvre

每天学习一点点算法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

javascript 跨浏览器的事件系统

从技术上讲,javascript并没有提供内置的系统来实现这个非常重要的事件驱动编程,不过得益于浏览器的DOM 事件模型,这缺点并没有过多地暴露出来。但实质上javascript之父也不能主宰这一切,他支持的网景也没有强大到让竞争对手乖乖地使用它的产品,微软搞了一个JScript,死去的Macromedia 搞了一个ActionScript,还有更多,听说这个分支挺复杂的。但借用浏览器内置的DOM事件模型,第一个后果是,想使用它就必须借助某个DOM对象,window,document或元素节点,第二个后果是由于每个浏览器对DOM的支持不一,不能确保事件模型的一致,第三个是由于基于DOM对象,很容易造成循环引用。微软打赢第一次浏览器战争后,就基本没有更新其DOM模型了,与不断更新向w3c,ecma等标准靠近的“标准浏览器”分成两大阵营。但标准浏览器内也不是磐石一块,如FF就不支持mousewheel而是DOMMouseScroll,opera的contextmenu 是不可控的。我们需要自己实现一下。眼下,双主都实现DOM2的事件模型,微软的是attachEvent为首,标准的是addeventListener,允许同一个元素可以绑定多个同类型的事件回调函数。网上许多addEvent函数都是用它们做成的,但也不可靠,首先,IE的回调函数没有强制绑定事件对象,而标准浏览器是强舞曲第一个参数即为事件对象,尽管我们可以用call函数实现强制绑定,但IE的事件对象与标准的也不一样,这里有许多工作要做。另一个,就是回调函数的执行顺序问题,IE是无规则的,标准是按绑定的先后顺序执行。因此,这两个函数也被否定。我打算用最原始的onXXXX来实现,绑定多个函数时,就把它们放入一个函数中,一个for循环搞定。

我们回顾一下上面的流程,这个事件系统其实是Dean大神的addEvent的一个改版。

  • 设置一个作为命名空间的对象。
  • 对Array做一些扩展。
  • attachEvent 函数用于绑定事件。具体做法在需要绑定事件的对象设置一个events属性,里面再按事件类型放置回调函数,由于有时我们可能在同一个元素上绑定2个或多个onclick事件什么的,因此它们必须是一个数组。最后用DOM0的原始方法添加一个onXXXX属性。
  • detachEvent 函数用于卸载事件,就是把events上对应类型的数组元素去掉。
  • handleEvent 执行回调函数。我们以onXXXX的形式绑定了一个全局的函数,它的作用是获得与修正事件对象,然后取得此事件类型对应的所有回调函数,然后依次把事件对象作为它们的第一个参数再执行它们。最后是处理一下冒泡。
  • fixEvent 修正事件对象。基本上就是让IE拥有标准浏览器的两个方法。

对于一般应用,它已够用了。但如果追求完全。我们还有许多东西都要用。首先把events这个庞大的对象放到元素上是非常不妥的,不利于集中管理。二,fixEvent并不彻底,如target,pageX/Y等标准浏览器下的属性,在IE中还是用不了。

首先是handleEvent 函数,现在是无论标准浏览器还是IE的事件对象都要修正,还在每次调用时为IE修正其currentTarget 值。

dom.handleEvent = function (event) {
   event =  event || window.event
   event = dom.fixEvent(event);
   event.currentTarget = this;//修正currentTarget
   var returnValue = true;
   var handlers = this.events[event.type];
   for(var i=0,n=handlers.length;i<n;i++){
     if (handlers[i](event) === false) {
       returnValue = false;
     }
   }
   return returnValue;
 };  

在我们介绍的新版fixEvent函数时,我们先隆重介绍我从jQuery剽窃过来的伪事件对象。

这个构造函数只实现了W3C事件模型的少许方法,那些属性去了哪?不急,我们在fixEvent方法中通过拷贝方式实现它们。为了区别原生事件对象与伪事件对象,我们在它上面添加了一个expando属性。

毫不犹豫地抄jQuery的方法,因为在所有类库中,jQuery的方法是最好提取的。

现在我们基本解决了文章中段提出的两个问题中的其中一个。要解决第一个我们就需要引入缓存系统了。这个留在下一部分讲。

如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码

posted on   司徒正美  阅读(3140)  评论(2编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示