jQuery 1.7 于11月3日正式发布 新的事件.on()、.off()被引入。官方博客声称提升了事件委派时的性能,并给出了1.6.4 和 1.7 版本的性能比较图:
语法:
- $(elements).on( events [, selector] [, data] , handler );
- $(elements).off( [ events ] [, selector] [, handler] );
Jquery 1.6.4 bind,ubbind、live,die、delegate,delegate、one事件源码
- jQuery.each(["bind", "one"], function( i, name ) {
- jQuery.fn[ name ] = function( type, data, fn ) {
- var handler;
- // Handle object literals
- if ( typeof type === "object" ) {
- for ( var key in type ) {
- this[ name ](key, data, type[key], fn);
- }
- return this;
- }
- if ( arguments.length === 2 || data === false ) {
- fn = data;
- data = undefined;
- }
- if ( name === "one" ) {
- handler = function( event ) {
- jQuery( this ).unbind( event, handler );
- return fn.apply( this, arguments );
- };
- handler.guid = fn.guid || jQuery.guid++;
- } else {
- handler = fn;
- }
- if ( type === "unload" && name !== "one" ) {
- this.one( type, data, fn );
- } else {
- for ( var i = 0, l = this.length; i < l; i++ ) {
- jQuery.event.add( this[i], type, handler, data );
- }
- }
- return this;
- };
- });
- unbind: function( type, fn ) {
- // Handle object literals
- if ( typeof type === "object" && !type.preventDefault ) {
- for ( var key in type ) {
- this.unbind(key, type[key]);
- }
- } else {
- for ( var i = 0, l = this.length; i < l; i++ ) {
- jQuery.event.remove( this[i], type, fn );
- }
- }
- return this;
- },
- jQuery.each(["live", "die"], function( i, name ) {
- jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
- var type, i = 0, match, namespaces, preType,
- selector = origSelector || this.selector,
- context = origSelector ? this : jQuery( this.context );
- if ( typeof types === "object" && !types.preventDefault ) {
- for ( var key in types ) {
- context[ name ]( key, data, types[key], selector );
- }
- return this;
- }
- if ( name === "die" && !types &&
- origSelector && origSelector.charAt(0) === "." ) {
- context.unbind( origSelector );
- return this;
- }
- if ( data === false || jQuery.isFunction( data ) ) {
- fn = data || returnFalse;
- data = undefined;
- }
- types = (types || "").split(" ");
- while ( (type = types[ i++ ]) != null ) {
- match = rnamespaces.exec( type );
- namespaces = "";
- if ( match ) {
- namespaces = match[0];
- type = type.replace( rnamespaces, "" );
- }
- if ( type === "hover" ) {
- types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
- continue;
- }
- preType = type;
- if ( liveMap[ type ] ) {
- types.push( liveMap[ type ] + namespaces );
- type = type + namespaces;
- } else {
- type = (liveMap[ type ] || type) + namespaces;
- }
- if ( name === "live" ) {
- // bind live handler
- for ( var j = 0, l = context.length; j < l; j++ ) {
- jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
- { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
- }
- } else {
- // unbind live handler
- context.unbind( "live." + liveConvert( type, selector ), fn );
- }
- }
- return this;
- };
- });
- delegate: function( selector, types, data, fn ) {
- return this.live( types, data, fn, selector );
- },
- undelegate: function( selector, types, fn ) {
- if ( arguments.length === 0 ) {
- return this.unbind( "live" );
- } else {
- return this.die( types, null, fn, selector );
- }
- }
Jquery 1.7 bind,ubbind、live,die、delegate,delegate、one事件源码
- one: function( types, selector, data, fn ) {
- return this.on.call( this, types, selector, data, fn, 1 );
- },
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
- live: function( types, data, fn ) {
- jQuery( this.context ).on( types, this.selector, data, fn );
- return this;
- },
- die: function( types, fn ) {
- jQuery( this.context ).off( types, this.selector || "**", fn );
- return this;
- },
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
- }
源码对比中不难看出Jquery 1.7 所有的事件委派都是基于这个新引入的 .on()和.off()。性能提示了多少我们肉眼没办法察觉到,但通过源代码分析性能的提升是肯定的。
.on()和.off()事件源码
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
- var origFn, type;
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
- // ( types-Object, data )
- data = selector;
- selector = undefined;
- }
- for ( type in types ) {
- this.on( type, selector, data, types[ type ], one );
- }
- return this;
- }
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return this;
- }
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return this.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- });
- },
- off: function( types, selector, fn ) {
- if ( types && types.preventDefault && types.handleObj ) {
- // ( event ) dispatched jQuery.Event
- var handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
- // ( types-object [, selector] )
- for ( var type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each(function() {
- jQuery.event.remove( this, types, fn, selector );
- });
- }
应用举例:
- <button id="theone">Does nothing...</button>
- <button id="bind">Add Click</button>
- <button id="unbind">Remove Click</button>
- <div style="display:none;">Click!</div>
- <script>
- function aClick() {
- $("div").show().fadeOut("slow");
- }
- $("#bind").click(function () {
- $("body").on("click", "#theone", aClick)
- .find("#theone").text("Can Click!");
- });
- $("#unbind").click(function () {
- $("body").off("click", "#theone", aClick)
- .find("#theone").text("Does nothing...");
- });
- </script>
- <p>官方推荐直接使用.on()和.off()事件,以下是新旧事件应用示例:</p>
- <pre>
- $('a').bind('click', myHandler);
- $('a').on('click', myHandler);
- $('form').bind('submit', { val: 42 }, fn);
- $('form').on('submit', { val: 42 }, fn);
- $(window).unbind('scroll.myPlugin');
- $(window).off('scroll.myPlugin');
- $('.comment').delegate('a.add', 'click', addNew);
- $('.comment').on('click', 'a.add', addNew);
- $('.dialog').undelegate('a', 'click.myDlg');
- $('.dialog').off('click.myDlg', 'a');
- $('a').live('click', fn);
- $(document).on('click', 'a', fn);
- $('a').die('click');
- $(document).off('click', 'a');