使用jQuery将事件从一个元素复制到另一个元素

23

我有一个类似这样的DOM结构:

<a href='javascript:void(0)' id='link1'>Element with  events bound initially</a>
<a href='javascript:void(0)' id='link2'>Element to which events are bound in future</a>

这是 JavaScript 代码:

$(function(){
    $('#link1').bind('click',function(){alert('do something to make me happy');})
});

现在,我希望在未来的某个时候将绑定在link1上的所有事件复制到link2上。我正在按照下面写的方式进行,请如果可能或可用的话提出一些更好的建议。

var _elmEvents = $(#link1).data('events');

if (_elmEvents) {
    $.each(_elmEvents, function (event, handlers) {
        $.each(handlers, function (j, handler) {
            $('#link2').bind(event, handler);
        });
    });
}

2
对于下面任何一个问题的评论,重要的是要注意jQuery现在已经更改,为了获取元素上的事件,必须使用$._data($("#foo")[0], "events")。(适用于jQuery v2.1.4)否则,您将从以下任何方法中收到未定义。参考:https://dev59.com/dHI-5IYBdhLWcg3wHUjP - Zanderi
7个回答

15
如果您想从一个对象复制所有事件到另一个对象而不进行克隆,可以通过直接访问事件数据来实现。
例如,如果您执行了以下操作:
$("#the_link").click(function(e){
    // do some stuff
    return false;
}).mouseover(function(e){
    // do some other stuff
});
您可以在元素的“事件”数据中访问这些事件关联。
var events = $("#the_link").data('events');

它将是一个对象,其键表示事件类型,每个键包含一组事件关联。不管怎样,这里有一个简单的例子,不考虑命名空间。

var events = $("#the_link").data('events');
var $other_link = $("#other_link");
if ( events ) {
    for ( var eventType in events ) {
        for ( var idx in events[eventType] ) {
            // this will essentially do $other_link.click( fn ) for each bound event
            $other_link[ eventType ]( events[eventType][idx].handler );
        }
    }
}

这个解决方案对我没有用,并且没有考虑事件命名空间。我添加了一个新的答案来处理它们(并且在我的情况下有效)。 - German Latorre
为什么这段代码会返回 "undefined":alert($("#a").data('events'));?请参见:https://jsfiddle.net/NabiKAZ/mbkL6gp3/1/ - Nabi K.A.Z.

5
这个在我的脚本中运行得非常好。
$.each($('#original').data('events'), function() {
  // iterate registered handler of original
  $.each(this, function() {
    $('#target').bind(this.type, this.handler);
  });
});

我在这里找到了它(来源):http://snipplr.com/view/64750/

它可以正常工作,但也许需要替换第一个参数:请查看下面Zanderi的评论。(感谢两位。) - mirek
为什么这段代码会返回 "undefined":alert($("#a").data('events'));?请参见:https://jsfiddle.net/NabiKAZ/mbkL6gp3/1/ - Nabi K.A.Z.

4

对于我使用的带有命名空间其他事件(如“paste”)的jQuery方法,接受的答案无法正常工作。

下面的方法对我有效:

function copyEvents(source, destination) {
    // Get source events
    var events = source.data('events');

    // Iterate through all event types
    $.each(events, function(eventType, eventArray) {
        // Iterate through every bound handler
        $.each(eventArray, function(index, event) {
            // Take event namespaces into account
            var eventToBind = event.namespace.length > 0
                ? (event.type + '.' + event.namespace)
                : (event.type);

            // Bind event
            destination.bind(eventToBind, event.data, event.handler);
        });
    });
}

1

您可以克隆一个元素并随意操作新元素,但是jQuery没有提供一种简单的方法来从一个元素复制事件处理程序到另一个元素。不过,实现这个功能的代码如下:

var events = jQuery.data( originalElement, "events" );

for ( var type in events ) {
    for ( var handler in events[ type ] ) {
        jQuery.event.add( targetElement, type, events[ type ][ handler ], events[ type ][ handler ].data );
    }
}

但由于它在某种程度上依赖于jQuery内部,我会尝试使用clone方法来解决。


0

这是基于Brandons的工作,但更新以适用于所有jQuery版本。已在1.6.42.0.x上进行测试。

/**
 * Logic for copying events from one jQuery object to another.
 *
 * @private 
 * @name jQuery.event.copy
 * @param jQuery|String|DOM Element jQuery object to copy events from. Only uses the first matched element.
 * @param jQuery|String|DOM Element jQuery object to copy events to. Copies to all matched elements.
 * @type undefined
 * @cat Plugins/copyEvents
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * @author Yannick Albert (mail@yckart.com || http://yckart.com)
 */
jQuery.event.copy = function (from, to) {
    from = from.jquery ? from : jQuery(from);
    to = to.jquery ? to : jQuery(to);

    var events = from[0].events || jQuery.data(from[0], "events") || jQuery._data(from[0], "events");
    if (!from.length || !to.length || !events) return;

    return to.each(function () {
        for (var type in events)
        for (var handler in events[type])
        jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
    });
};

0
$.fn.copyEvents = function( to, filter )
{
    var to = to.jquery ? to : jQuery(to);
    var filter = filter ? filter.split(" ") : null;
    var events = this[0].events || jQuery.data(this[0], "events") || jQuery._data(this[0], "events");

    return this.each(function()
    {
        if (!to.length || !events) {
            return;
        }

        $.each(events, function(eventType, eventArray) {
            $.each(eventArray, function(index, event) {
                var eventToBind = event.namespace.length > 0
                    ? (event.type + '.' + event.namespace)
                    : (event.type);
                if (filter && $.inArray(eventToBind, filter) == -1) {
                    return true;
                }
                to.bind(eventToBind, event.data, event.handler);
            });
        });
    });
}

// Add some events to a element
$('#element').click(function() { });
$('#element').dblclick(function() { });
$('#element').change(function() { });

// Default usage, copy *all* events from one element to another
$('#element').copyEvents('#another-element');

// ... or you can copy only specific event types
$('#element').copyEvents('#another-element', 'change click');

原文在这里 https://blog.armin-pfaeffle.de/2014/08/jquery-copy-events-from-one-element-to-another


0

根据更新的jQuery编辑了@Rikco的答案。

function assingEvents() {
     //if you have multiple just use jQuery._data(jQuery('.copy-from-single-item')[0]
     jQuery.each(jQuery._data(jQuery('.copy-from-single-item'), 'events'), function()  {
       // iterate registered handler of original
       jQuery.each(this, function() {
        var parentEvent = this;
        jQuery.each(jQuery('.copy-to-multiple-item'),
            function() {
                jQuery(this).bind(parentEvent.type, parentEvent.handler);
            });
       });
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接