深入学习jquery源码之on()和off()与one()

东郭思远
2023-12-01

深入学习jquery源码之on()和off()与one()

on(events,[selector],[data],fn)

概述

在选择元素上绑定一个或多个事件的事件处理函数。

on()方法绑定事件处理程序到当前选定的jQuery对象中的元素。在jQuery 1.7中,.on()方法 提供绑定事件处理程序所需的所有功能。帮助从旧的jQuery事件方法转换,see .bind().delegate(), 和 .live(). 要删除的.on()绑定的事件,请参阅.off()。要附加一个事件,只运行一次,然后删除自己, 请参阅.one()

参数

events,[selector],[data],fn

events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" 。

selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。如果选择的< null或省略,当它到达选定的元素,事件总是触发。

data:当一个事件被触发时要传递event.data给事件处理函数。

fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。

events-map,[selector],[data]

events-map:个用字符串表示的,一个或多个空格分隔的事件类型和可选的命名空间,值表示事件绑定的处理函数。

selector:一个选择器字符串过滤选定的元素,该选择器的后裔元素将调用处理程序。如果选择是空或被忽略,当它到达选定的元素,事件总是触发。

data:当一个事件被触发时要传递event.data给事件处理函数。

使用

单击时在alert()中显示段落的文本:

$("p").on("click", function(){
alert( $(this).text() );
});

将数据传递给事件处理程序,该处理程序在此处按名称指定:

function myHandler(event) {
alert(event.data.foo);
}
$("p").on("click", {foo: "bar"}, myHandler)

取消表单提交操作并通过返回false来阻止事件冒泡:

$("form").on("submit", false)

使用.preventDefault()仅取消默认操作。

$("form").on("submit", function(event) {
  event.preventDefault();
});

使用.stopPropagation()停止通过冒泡提交事件而不阻止表单提交。

$("form").on("submit", function(event) {
  event.stopPropagation();
});

控制上传附件的个数

$("#dealPicture").mouseover(function(){
	
	var tbodyLength = $(this).siblings().find("tbody[id='dealPicture_list_table']").find("tr")
	var flag = true;
	if($(tbodyLength).length==0){
		flag = false;
	}

	if(flag){
		$(".layui-input-block button[id='dealPicture']").off('click').on('click',a) }
	 if(!flag){
		$(".layui-input-block button[id='dealPicture']").off('click',a).on('click',upload);
		$("#dealPicture").trigger('click');
	 }

})

function a(){
		layer.msg("附件仅能上传一个");
	};
	function upload(){

	}

 

 

off(events,[selector],[fn])

概述

在选择元素上移除一个或多个事件的事件处理函数。

off() 方法移除用.on()绑定的事件处理程序。有关详细信息,请参阅该网页上delegated和directly绑定事件。特定的事件处理程序可以被移除元素上提供事件的名称,命名空间,选择器,或处理函数名称的组合。当有多个过滤参数,所提供的参数都必须匹配的事件处理程序被删除。

如果一个简单的事件名称,比如提供"click",所有 这种类型的事件(包括直接和委派)从jQuery设置的元素上删除。当编写代码,将作为一个插件使用,或者干脆当一个大的代码基础工作,最好的做法是安装和取下使用命名空间的事件,从而使代码不会无意中删除其他代码附加事件处理程序。在一个特定的命名空间中的所有类型的所有事件,可以从一个元素中删除,只是提供了一个命名空间,比如 ".myPlugin"。至少,无论是命名空间或事件名称必须提供。

要删除特定的委派事件处理程序,提供一个selector 的参数。选择器字符串必须是完全匹配递到.on()事件处理程序附加的选择器。要删除非委托元素上的所有事件,使用特殊值 "**" 。

处理程序也可以删除handler参数指定名称的函数。当jQuery的绑定一个事件处理程序,它分配一个唯一的ID给处理函数。函数用jQuery.proxy()代理或类似有相同的唯一ID机制(代理函数),因此,通过代理处理程序.off 可能会删除比预期更多的处理程序。在这些情况下,最好是附加和移除事件处理程序,使用命名空间。

和.on()一样,你可以传递一个 events-map>参数明确的指定而不是用events 和 handler作为单独参数。键事件和/或命名空间;值是处理函数或为false的特殊价值。

参数

events,[selector],[fn]

events:一个或多个空格分隔的事件类型和可选的命名空间,或仅仅是命名空间,比如"click", "keydown.myPlugin", 或者 ".myPlugin".

selector:一个最初传递到.on()事件处理程序附加的选择器。

fn:事件处理程序函数以前附加事件上,或特殊值false.

events-map,[selector]

events-map:一个用字符串表示的,一个或多个空格分隔的事件类型和可选的命名空间,值表示先前事件绑定的处理函数。

selector:一个最初传递到.on()事件处理程序附加的选择器。

从所有段落中删除所有事件处理程序:

$("p").off()

从所有段落中删除所有委派的点击处理程序:

$("p").off( "click", "**" )

通过将其作为第三个参数传递,只删除一个先前绑定的处理程序

var foo = function () {
  // code to handle some kind of event
};

// ... now foo will be called when paragraphs are clicked ...
$("body").on("click", "p", foo);


// ... foo will no longer be called.
$("body").off("click", "p", foo); 

解除所有委托事件处理程序的名称空间:

var validate = function () {
  // code to validate form entries
};

// delegate events under the ".validator" namespace
$("form").on("click.validator", "button", validate);

$("form").on("keypress.validator", "input[type='text']", validate); 

// remove event handlers in the ".validator" namespace

$("form").off(".validator");

 

one(type,[data],fn)

概述

为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。

在每个对象上,这个事件处理函数只会被执行一次。其他规则与bind()函数相同。这个事件处理函数会接收到一个事件对象,可以通过它来阻止(浏览器)默认的行为。如果既想取消默认的行为,又想阻止事件起泡,这个事件处理函数必须返回false。

多数情况下,可以把事件处理函数定义为匿名函数(见示例一)。在不可能定义匿名函数的情况下,可以传递一个可选的数据对象作为第二个参数(而事件处理函数则作为第三个参数),

参数

type,[data],fn  String,Object,Function

type:添加到元素的一个或多个事件。由空格分隔多个事件。必须是有效的事件。

data:将要传递给事件处理函数的数据映射

fn:每当事件触发时执行的函数。

当所有段落被第一次点击的时候,显示所有其文本。

$("p").one("click", function(){
  alert( $(this).text() );
});

 

jquery源码

    jQuery.fn.extend({
        on: function (types, selector, data, fn, /*INTERNAL*/ one) {
            var type, origFn;

            // Types can be a map of types/handlers
            if (typeof types === "object") {
                // ( types-Object, selector, data )
                if (typeof selector !== "string") {
                    // ( types-Object, data )
                    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);
            });
        },
        one: function (types, selector, data, fn) {
            return this.on(types, selector, data, fn, 1);
        },
        off: function (types, selector, fn) {
            var handleObj, type;
            if (types && types.preventDefault && types.handleObj) {
                // ( event )  dispatched jQuery.Event
                handleObj = types.handleObj;
                jQuery(types.delegateTarget).off(
                    handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
                    handleObj.selector,
                    handleObj.handler
                );
                return this;
            }
            if (typeof types === "object") {
                // ( types-object [, selector] )
                for (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);
            });
        }
    });
	
	
	
	    /*
     * Helper functions for managing events -- not part of the public interface.
     * Props to Dean Edwards' addEvent library for many of the ideas.
     */
    jQuery.event = {

        global: {},

        add: function (elem, types, handler, data, selector) {
            var tmp, events, t, handleObjIn,
                special, eventHandle, handleObj,
                handlers, type, namespaces, origType,
                elemData = jQuery._data(elem);

            // Don't attach events to noData or text/comment nodes (but allow plain objects)
            if (!elemData) {
                return;
            }

            // Caller can pass in an object of custom data in lieu of the handler
            if (handler.handler) {
                handleObjIn = handler;
                handler = handleObjIn.handler;
                selector = handleObjIn.selector;
            }

            // Make sure that the handler has a unique ID, used to find/remove it later
            if (!handler.guid) {
                handler.guid = jQuery.guid++;
            }

            // Init the element's event structure and main handler, if this is the first
            if (!(events = elemData.events)) {
                events = elemData.events = {};
            }
            if (!(eventHandle = elemData.handle)) {
                eventHandle = elemData.handle = function (e) {
                    // Discard the second event of a jQuery.event.trigger() and
                    // when an event is called after a page has unloaded
                    return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
                        jQuery.event.dispatch.apply(eventHandle.elem, arguments) :
                        undefined;
                };
                // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
                eventHandle.elem = elem;
            }

            // Handle multiple events separated by a space
            types = (types || "").match(rnotwhite) || [""];
            t = types.length;
            while (t--) {
                tmp = rtypenamespace.exec(types[t]) || [];
                type = origType = tmp[1];
                namespaces = (tmp[2] || "").split(".").sort();

                // There *must* be a type, no attaching namespace-only handlers
                if (!type) {
                    continue;
                }

                // If event changes its type, use the special event handlers for the changed type
                special = jQuery.event.special[type] || {};

                // If selector defined, determine special event api type, otherwise given type
                type = (selector ? special.delegateType : special.bindType) || type;

                // Update special based on newly reset type
                special = jQuery.event.special[type] || {};

                // handleObj is passed to all event handlers
                handleObj = jQuery.extend({
                    type: type,
                    origType: origType,
                    data: data,
                    handler: handler,
                    guid: handler.guid,
                    selector: selector,
                    needsContext: selector && jQuery.expr.match.needsContext.test(selector),
                    namespace: namespaces.join(".")
                }, handleObjIn);

                // Init the event handler queue if we're the first
                if (!(handlers = events[type])) {
                    handlers = events[type] = [];
                    handlers.delegateCount = 0;

                    // 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.add) {
                    special.add.call(elem, handleObj);

                    if (!handleObj.handler.guid) {
                        handleObj.handler.guid = handler.guid;
                    }
                }

                // Add to the element's handler list, delegates in front
                if (selector) {
                    handlers.splice(handlers.delegateCount++, 0, handleObj);
                } else {
                    handlers.push(handleObj);
                }

                // Keep track of which events have ever been used, for event optimization
                jQuery.event.global[type] = true;
            }

            // Nullify elem to prevent memory leaks in IE
            elem = null;
        },

        // Detach an event or set of events from an element
        remove: function (elem, types, handler, selector, mappedTypes) {
            var j, handleObj, tmp,
                origCount, t, events,
                special, handlers, type,
                namespaces, origType,
                elemData = jQuery.hasData(elem) && jQuery._data(elem);

            if (!elemData || !(events = elemData.events)) {
                return;
            }

            // Once for each type.namespace in types; type may be omitted
            types = (types || "").match(rnotwhite) || [""];
            t = types.length;
            while (t--) {
                tmp = rtypenamespace.exec(types[t]) || [];
                type = origType = tmp[1];
                namespaces = (tmp[2] || "").split(".").sort();

                // Unbind all events (on this namespace, if provided) for the element
                if (!type) {
                    for (type in events) {
                        jQuery.event.remove(elem, type + types[t], handler, selector, true);
                    }
                    continue;
                }

                special = jQuery.event.special[type] || {};
                type = (selector ? special.delegateType : special.bindType) || type;
                handlers = events[type] || [];
                tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)");

                // Remove matching events
                origCount = j = handlers.length;
                while (j--) {
                    handleObj = handlers[j];

                    if ((mappedTypes || origType === handleObj.origType) &&
                        (!handler || handler.guid === handleObj.guid) &&
                        (!tmp || tmp.test(handleObj.namespace)) &&
                        (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) {
                        handlers.splice(j, 1);

                        if (handleObj.selector) {
                            handlers.delegateCount--;
                        }
                        if (special.remove) {
                            special.remove.call(elem, handleObj);
                        }
                    }
                }

                // Remove generic event handler if we removed something and no more handlers exist
                // (avoids potential for endless recursion during removal of special event handlers)
                if (origCount && !handlers.length) {
                    if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {
                        jQuery.removeEvent(elem, type, elemData.handle);
                    }

                    delete events[type];
                }
            }

            // Remove the expando if it's no longer used
            if (jQuery.isEmptyObject(events)) {
                delete elemData.handle;

                // removeData also checks for emptiness and clears the expando if empty
                // so use it instead of delete
                jQuery._removeData(elem, "events");
            }
        }
    };

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 类似资料: