原始代码:
// closure_library_path/closure/goog/events/events.js L222
// goog.events.listen = function(src, type, listener, opt_capt, opt_handler) {....
// Attach the proxy through the browser's API
if (src.addEventListener) {
if (src == goog.global || !src.customEvent_) {
src.addEventListener(type, proxy, capture);
}
} else {
src.attachEvent(goog.events.getOnString_(type), proxy);
}
Closure 在会检测要绑定事件的目标对象上的 customEvent_
属性,此值为 true
时它表示目标对象不是 DOM 原生对象,而是一个 goog.events.EventTarget
实例,同时这个事件的可能是一个自定义的事件。
customEvent_
属性来源:
// closure_library_path/closure/goog/events/eventtarget.js L72
/**
* Used to tell if an event is a real event in goog.events.listen() so we don't
* get listen() calling addEventListener() and vice-versa.
* @type {boolean}
* @private
*/
goog.events.EventTarget.prototype.customEvent_ = true;
高级编译模式时,customEvent_
被编译成了其他随机的短名称,比如有 pw、tw、Lx:
env 1:
if (a.addEventListener) {
if (a == q || !a.pw)
a.addEventListener(b, j, d)
}
env 2:
if (a.addEventListener) {
if (a == q || !a.tw)
a.addEventListener(b, j, d)
}
env 3:
if (a.addEventListener) {
if (a == q || !a.Lx)
a.addEventListener(b, j, d)
}
同时,如果有一个类似的表单,表单的 pw 属性为 input 元素,而 customEvent_
也被编译成 pw 短名称,此时 goog.events.listen
绑定事件将失效,如:
<form id="myform">
<input name="pw">
</form>
<script>
var form = document.forms['myform']
// input element
console.log(form.pw)
// failed to listen
goog.events.listen(form, 'submit', fn)
</script>
暂时想了两个办法:
- 修改源码
if (src == goog.global || src.customEvent_ !== true) {..}
- 或 input 使用足够长的 name 属性,不可靠。
- 更换 closure library 版本,跳过这个编译结果,不可靠.
现在也只发现只有 form 会有绑定失效的情况。
关于 input 遍历:
form.name
访问肯定看着就很恶心,还有一种推荐的办法:form.elements['name']
,这样可以免去元素遍历,速度更快:比如 jQuery.serializeArray 方法:
https://github.com/jquery/jquery/blob/master/src/ajax.js#L238
还有 goog.dom.forms 里面多个方法的实现:
http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/dom/forms.js
Closure 为了保障表单能正常提交(比如无 JS 也能工作),不能也不会在编译时重命名表单域的 name 。
同时查了一下起源:
form.name,从 DOM1就存在了,往后为了兼容也一直保留了:
DOM1
http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-40002357
DOM2
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-40002357
form.elements 从 DOM2 开始有了:
https://developer.mozilla.org/en/DOM/form.elements