什么时候要用到自定义函数?有些浏览器并不兼容某类型的事件,如IE6~8不支持hashchange事件,你无法通过jQuery(window).bind('hashchange', callback)来绑定这个事件,这个时候你就可以通过jQuery自定义事件接口来模拟这个事件,做到跨浏览器兼容。
原理
jQuery(elem).bind(type, callbakc)实际上是映射到 jQuery.event.add(elem, types, handler, data)这个方法,每一个类型的事件会初始化一次事件处理器,而传入的回调函数会以数组的方式缓存起来,当事件触发的时候处理器将依次执行这个数组。
jQuery.event.add方法在第一次初始化处理器的时候会检查是否为自定义事件,如果存在则将会把控制权限交给自定义事件的事件初始化函数,同样事件卸载的jQuery.event.remove方法在删除处理器前也会检查此。
如jQuery源码:
初始化处事件处理器
// Check for a special event handler // Only use addEventListener/attachEvent if the special // events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } }
卸载处理器:
if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); }
入口
jQuery.event.special[youEvent] = { /** * 初始化事件处理器 - this指向元素 * @param 附加的数据 * @param 事件类型命名空间 * @param 回调函数 */ setup: function (data, namespaces, eventHandle) { }, /** * 卸载事件处理器 - this指向元素 * @param 事件类型命名空间 */ teardown: function (namespaces) { } };
事实上jQuery自定义事件那些接收的参数有点鸡肋,需要hack与能hack的事件就那么一点点,且限制颇多,一般情况下很少使用到。
接下来我们做一个最简单的自定义插件,给jQuery提供input跨浏览器事件支持。input事件不同于keydown与keyup,它不依赖键盘响应,只要值改变都会触发input事件,比如粘贴文字、使用在线软键盘等。