QWrap简介之:EventW ---Event包装

事件在dom操作中,也有着重要的意义。不过,对于项目程序员同学,只需知道怎么用就可以了。如果在看本文之前,还没有理解清楚标准的dom event,那么请忽略本文,免得产生更多的纠结。
事件对象与节点对象一样,无法通过渲染原生dom的Event的原型来达到扩展与兼容的效果,所以,也采用Wrap模型来解决这个问题。
EventW就是针对Event的包装。它的核是原生的event。
前面介绍NodeW是按进化的思路由浅入深的介绍,反个方向,从最终用法来反观EventW的实现。

event在事件监控中会用到。
为元素添加事件,通常的用法应该是这样的:
//<div class="mydiv">content1<a href="http://www.baidu.com">baidu</a></div>
var handler=function(e){
alert(e.type);
//事件类型
alert(this.innerHTML); //this是被监控的节点对象
alert(e.target.innerHTML); //this.target是触发事件的对象
alert(e.preventDefault()); //阻止事件默认操作
};
W(
'div.aaa').on('click', handler);

熟悉浏览器的同学可能知道,对于标准浏览器,上面的用法很自然;但是对于某些版本的IE,如果on是直接调用原生的attachEvent,则上面的代码会不是预期效果,
其中的e.target会是空,而this会是window,等等,很多地方不符合预期。
但是,事实上我们可以这么用。原因是什么?
因为,NodeW.prototype里的on,做了一个偷梁换柱的小动作:它把handler函数进行了一个变换,之后将变换的结果当作新的监控函数传给dom的相关方法。
看一下on静态实现的简单示意代码:
EventTargetH.on = function(element, sEvent, handler) {
var _listener = listener(element, sEvent, handler);
EventTargetH.addEventListener(element, name, _listener);
};
function listener(element, name, handler) {
return function(e) {
return fireHandler(element, e, handler, name);
};
}

这个偷梁换柱的小动作,让我们把handler的this与arguments、甚至包括触发时机的主动权从浏览器那里抢过来,放到fireHandler里去了。
有了这个主动权,我们让handler里的this,指向被监控的节点;让arguments[0]变成了一个确定存在的e,不过,这个e不是原生的“e||window.event”,而一个新的东西:EventW的实例,相当于:e=new EventW(e||window.event)。

那我们看下EventW是个什么东东吧:
/**
* @class EventW Event Wrap,event对象包装器
* @namespace QW
*/
(
function() {
var mix = QW.ObjectH.mix,
methodize
= QW.HelperH.methodize;

QW.EventW
= function(e) {
this.core = e || window.event; //core 原生Event实例
this.target = this.getTarget(); //target 事件触发的元素
this.relatedTarget = this.getRelatedTarget(); //relatedTarget事件的相关元素.
this.pageX = this.getPageX();
this.pageY = this.getPageY();
this.detail = this.getDetail();
this.keyCode = this.getKeyCode();
this.ctrlKey = this.getCtrlKey();
this.shiftKey = this.getShiftKey();
this.altKey = this.getAltKey();
this.button = this.core.button;
this.clientX = this.core.clientX;
this.clientY = this.core.clientY;
this.type = this.core.type;
};

mix(QW.EventW.prototype, methodize(QW.EventH,
'core'));
}());


看起来很简单,其实就是一个core为原生event的对象,不过在构造时,同时仿照dom event标准给他赋了一套属性。
可能有的同学会问:这里的this.getTarget、this.getRelatedTarget等方法是哪里来的?
答:是这一句话带来的:“mix(QW.EventW.prototype, methodize(QW.EventH, 'core'));”
这一句话的意思是:将EventH里的所有静态方法,转变成EventW的原型方法。除了在构造器里用到的,还包括preventDefault、cancelBubble等方法,所以,在实际应用中,可以像原生的event一样这样调用:e.preventDefault()来阻止默认事件。
明白了这些思路,代码看起来很简单吧。

可能会有同学有疑惑,频繁创建EventW,不会有效率问题么,尤其是在mousemove时?
虽说是频繁创建并且赋属性,不过都是简单调用与赋值,就算鼠标频率调到100hz,这个创建时间也是小到可以忽略不计的。----具体没测过相关数值,但在目前所有的应用项目中,没发现有问题。

QWrap中,与evnet相关的类与命名空间共有三个:
EventH:http://dev.qwrap.com/resource/js/dom/event.h.js
EventTargetH:http://dev.qwrap.com/resource/js/dom/eventtarget.h.js
EventW:http://dev.qwrap.com/resource/js/dom/event.w.js
EventH与EventTargetH都是满足“纯洁、静态、针对性”特征的Helper,理解起来相对容易点。
在组件开发中,为了无依赖化,可能会直接用到上面两个Helper,
而在使用QWrap的项目中,它们几乎不会用到,因为EventH的功能,已传递给EventW了;而EventTargetH的功能,也会传递给NodeW。
这种功能的传递与转化,就是QWrap所提的retouch机制,且听下回分解。

附:QWrap网址:http://www.qwrap.com

posted on 2011-03-26 14:51  JKisJK  阅读(696)  评论(2编辑  收藏  举报

导航