在不嵌套事件侦听器的情况下侦听数组中对对象的更改 [英] Listen for changes against an Object In an array without nesting event listeners

查看:88
本文介绍了在不嵌套事件侦听器的情况下侦听数组中对对象的更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(免责声明:这个问题比标题说明的要简单得多!)

(disclaimer: this question is much simpler than the title suggests!)

在我的程序体系结构中,我经常遇到一个问题,那就是听模型的更改.

I have a re-occuring problem in my program architecture with listening to changes against a model.

我已经建立了一些集合(很像Backbone.js中的集合),它们只是围绕数组构建的轻量级类.该集合是模型的集合.当用户对模型进行更改时,我总是以可怕的嵌套事件结束.这是我要避免的典型,简单方案:

I have set-up some collections (much like in Backbone.js) which are just lightweight classes built around an array. The collection is a collection of models. When the user makes changes to a model I keep ending up with dreadful nested events. This is a typical, simple, scenario that I'm trying to avoid:

$("#user-details").on("click", "#save", onSaveClick);

function onSaveClick()
{       
    var givennames = $("#givenname").val(),

    // Get the model from the collection
    var user = users.get($(this).attr("data-id"));

    // set the property
    user.set("GivenNames", givennames);

    // listen for the save event
    $(user).on("save", function(){
        // Alert the view
    });

    user.save();    // save event triggers a "save" event on the model
}

如果同一用户被保存两次,则该事件将被多次添加/触发.有更好的模式吗?

If the same user is saved twice the event gets added/fired multiple times. Is there a better pattern for this?

该事件是否应该在整个收藏中冒起,并可能以这种方式处理?

Should the event be bubbling up through the collection and handled that way perhaps?

这是一个实际的例子(我最as愧的那个例子)

Here's an actual example (the one I'm most ashamed of)

$("#user-devices").on("click", ".device button", function(){

            var button = $(this),
                deviceId = $(this).closest(".device").attr("data-id"),
                device = userDevices.get(deviceId);


            $(device).on("activate", function(event, device){

                button.removeClass("btn-danger").addClass("btn-success")

                $("#activation-dialog").modal("show");
            })

            if (device.get("Active") === "1")
            {
                $("#reactivation-warning-dialog").modal("show");
                $("#reactivation-warning-dialog .btn-primary").on("click", function(){
                    device.activate();
                });

            }
            else
            {
                device.activate();  
            }
        });

推荐答案

您可以仅检查save事件是否已绑定,在这种情况下,无需再次绑定它,如下所示:

You could just check if the save event is already binded, in that case not bind it again, like this:

// if no 'save' event already binded
if (!$(user).data('events') || !$(user).data('events').save) { 
    // listen for the save event
    $(user).on("save", function(){
        // Alert the view
    });
}

查看正在运行的 示例

See working example

要在上面放些糖,我们可以将"检查事件是否存在"逻辑放入自定义jquery伪选择器中,该逻辑的定义如下:

To put some sugar on top, we can make the "check if event exist" logic into a custom jquery pseudo-selector, that would be defined as follows:

$.expr[':'].hasEvent = function(obj, idx, meta, stack) {
    return ($(obj).data('events') != undefined 
            && $(obj).data('events')[meta[3]] != undefined);
};

然后您可以通过以下方式使用它:

Then you can use it this way:

$(user).not(":hasEvent(save)").on("save", function(){
     // Alert the view
});

工作中 示例

更新JQUERY> = 1.8

jQuery 1.8 开始,对event对象进行了一些更改,使我的上述代码无法正常工作,请参见

Starting with jQuery 1.8 there were some changes to the events object which makes my above code not to work, see this excerpt from the jQuery 1.8 release notes:

$(element).data(事件"):在1.6版中,jQuery分离了其 用户数据中的内部数据,以防止名称冲突. 但是,有些人正在使用内部未记录的事件" 数据结构,因此我们仍然可以通过 .data().现在已在1.8中将其删除,但是您仍然可以转到 事件数据,用于通过$._data(element, "events")进行调试. 请注意,这不是受支持的公共接口.实际数据 各个版本的结构可能会不兼容地发生变化.

$(element).data("events"): In version 1.6, jQuery separated its internal data from the user’s data to prevent name collisions. However, some people were using the internal undocumented "events" data structure so we made it possible to still retrieve that via .data(). This is now removed in 1.8, but you can still get to the events data for debugging purposes via $._data(element, "events"). Note that this is not a supported public interface; the actual data structures may change incompatibly from version to version.

因此,在这里,我为上述示例发布了 jQuery> = 1.8 的更新版本:

So here I post the jQuery >= 1.8 updated versions for of my above examples:

检查save事件是否已绑定,在这种情况下,请不要再次绑定它:

Checking if the save event is already binded, in that case not bind it again:

// if no 'save' event already binded
if (!$._data(user, 'events') || !$._data(user, 'events').save) { 
    // listen for the save event
    $(user).on("save", function(){
        // Alert the view
    });
}

和自定义jquery伪选择器:

And the custom jquery pseudo-selector:

$.expr[':'].hasEvent = function(obj, idx, meta, stack) {
    return ($._data(obj, 'events') != undefined 
            && $._data(obj, 'events')[meta[3]] != undefined);
};

这篇关于在不嵌套事件侦听器的情况下侦听数组中对对象的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆