GWT一个页面包含多个模块时出现的问题

GWT版本:1.4.61
浏览器版本:IE6

当一个页面里包含了多个GWT模块时,有可能在发生鼠标事件(主要是mouseover事件)的时候,IE会报javascript错误:Object doesn't support this property or method(对象不支持此属性或方法)。经过测试,GWT编译时如果不使用混淆,则不会出错。

经网上搜索和自己分析得知,该问题主要是由于GWT的浏览器事件管理机制在多个GWT模块间发生冲突造成。

GWT的网站上提供了一个出错的案例,在下面的网址可以找到说明和案例下载:
[url=http://code.google.com/p/google-web-toolkit/issues/detail?id=1804#c2]Issue 1804: JavaScript Errors generated on mouse events with 2 Modules on 1 Page [/url]
本文后面也附上了这个案例的下载。另外在GWT网站的其他页面也有相关的讨论和解决方案:
[url=http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/9214a89923693195/528b195182241737#528b195182241737]JavaScript Error on Mouse Events with 2 Modules on 1 Page 选项 [/url]
[url=http://code.google.com/p/google-web-toolkit/issues/detail?id=1788]Issue 1788: Only the last module to call DOMImplStandard.init() is able to preview events [/url]
[url=http://code.google.com/p/google-web-toolkit/issues/detail?id=1546]Issue 1546: Eliminate DOM modifications to body element [/url]

首先说一下GWT的事件处理机制。GWT模块里的所有事件都会注册到$wnd.__dispatchEvent函数,如果一个页面存在多个模块,则每个模块都会将自己的组件的事件注册到自己定义的__dispatchEvent函数。

$doc.body.onclick = $doc.body.onmouseover = ... = $wnd.__dispatchEvent;

element.onclick = bits & 1 ? $wnd.__dispatchEvent : null;
...
element.XXX = bits & XX ? $wnd.__dispatchEvent : null;
//bits是每个组件上的一个事件的属性,用于判断是否注册了哪些事件,
//通过跟事件的位标志(如onclick是1)做位比较得知是否注册了该事件。


事件发生后,执行$wnd.__dispatchEvent函数:

var listener, cureElem = this;
while (curElem && !(listener = curElem.__listener))
curElem = curElem.parentElement;
if (listener)
com_google_gwt_user_client_DOM_dispatchEvent_Lcom_googel_gwt_user_client_Event_2Lcom_google_gwt_user_client_Element_2Lcom_google_gwt_user_client_EventListener_2($wnd.event, curElem, listener);

当listener存在的时候,最终会调用到如下代码:

listener.onBrwoserEvent__Lcom_google_gwt_user_client_Event_2(evt);


本来不同模块之间的着2段代码都是一致的,所以即使定义了多个__dispatchEvent方法也无所谓,问题是混淆之后,不同模块的组件的__listener属性对象的onBrwoserEvent__Lcom_google_gwt_user_client_Event_2函数会被混淆成不同的名字,如第一个模块叫a函数,第二个叫b函数。这样当多个模块在一个页面里时,有可能出现第一个模块的一个组件的事件发生后在第二个模块定义的__dispatchEvent函数里处理,结果就是调用了b函数,而这个函数在第一个模块的组件的listener属性对象里不存在,这时候就会报javascript错误了:Object doesn't support this property or method(对象不支持此属性或方法)。这也就是不混淆代码的时候就不出错的原因。

为什么多个模块之间的组件事件注册会发生冲突,这个问题我还没有搞清楚。目前的是测试结果表明,并不是所有情况下都会出现这个情况,只是在某些特殊的情况下才会出现,有空的时候我会将对所附的测试案例的分析补充到本文中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值