如何在Backbone View层次结构中“冒泡”事件?

时间:2012-02-22 23:54:45

标签: javascript event-handling backbone.js

我有一个骨干应用程序,其视图结构如下所示 - 请注意我为了简洁而删除了实现,模型,集合等:

NewsListView = Backbone.View.extend({

    el: $('li#newspane'),

    // This is what I would like to be able to do
    // events: { 'filtered': 'reset' }

    initialize: function() {
        _.bindAll(this);
    },

    render: function() {
    },

    reset: function(){
    }

});

FilterView = Backbone.View.extend({

    el: $('li.filter'),

    initialize: function() {
    },

    render: function() {
    },

    toggleFilter: function() {
    }

});

AllView = Backbone.View.extend({

    initialize: function() {

        this.newsListView = new NewsListView();
        this.filterView = new FilterView();

    }

});

基本上,每当调用FilterView的{​​{1}}函数时,我想触发一个名为toggleFilter()的事件或类似的事件,然后被{{1然后调用其filtered函数。如果没有将NewsListView对象的引用传递给我的reset(),我不确定如何向它发送事件。有什么想法吗?

6 个答案:

答案 0 :(得分:5)

你走在正确的轨道上。听起来你需要的是全球事件调度员。这里有一篇不错的文章和例子:http://www.michikono.com/2012/01/11/adding-a-centralized-event-dispatcher-on-backbone-js/

答案 1 :(得分:3)

您可以使用jquery事件和骨干事件属性的现有功能来执行此操作。

例如,不要在子视图中执行此操作:

this.trigger("yourevent", this);

改为:

this.$el.trigger("yourevent", this);

然后在您的子视图的父视图,祖父视图等的任何视图中,通过在该视图的事件对象上定义属性来侦听该视图的$ el上的事件:

events:{
    "yourevent":"yourhandler"
}

并在该视图上定义处理程序:

yourhandler:function(subview) {
}

所以这样,视图不需要知道后代视图的存在,只知道它感兴趣的事件的类型。如果导致事件的视图被破坏,则祖先视图中不需要更改任何内容。如果祖先视图被破坏,Backbone将自动分离处理程序。

警告:我还没有尝试过,所以某处可能存在问题。

答案 2 :(得分:1)

你应该查看Backbone.Courier插件,因为冒泡事件是一个完美的用例:

https://github.com/dgbeck/backbone.courier

答案 3 :(得分:1)

我发现触发和侦听事件的最简单方法就是使用Backbone对象本身。它已经混合了事件函数,所以你可以触发例如:

Backbone.trigger('view:eventname',{extra_thing:whatever, thing2:whatever2});

然后,在您的应用的任何其他骨干视图中,您可以收听此事件,例如:

Backbone.on('view:eventname', function(passed_obj) {
    console.log(passed_obj.extra_thing);
});

我不完全确定不使用Backbone对象作为事件处理程序的优点是什么,而是创建一个单独的对象来执行它,但对于快速和脏的工作,上面的工作正常。 HTH!

注意:这样做的一个缺点是每个听众都会听到"以这种方式触发的每一个事件。不确定那个大O是什么,但是要小心不要用很多这些东西重载你的观点。再说一次:这很快又脏! :)

答案 4 :(得分:0)

所以,我提出了一个解决方案 - 创建一个扩展Backbone.Events的对象,并将其作为参数传递给多个视图。这几乎就像是在演员之间传递消息,或者某种东西。无论如何 - 如果其他人需要快速解决方案,我会将此作为答案发布,但我不会接受答案。这感觉很糟糕。我仍然希望看到更好的解决方案。

NewsListView = Backbone.View.extend({
    el: $('li#newspane'),

    // Too bad this doesn't work, it'd be really convenient
    // events: { 'filtered': 'reset' }

    initialize: function() {
        _.bindAll(this);
        // but at least this does
        this.options.eventProxy.bind('filtered', this.reset);
    },
    render: function() {},
    reset: function() {}
});

FilterView = Backbone.View.extend({
    el: $('li.filter'),

    initialize: function() {},
    render: function() {},
    toggleFilter: function() {
        this.options.eventProxy.trigger('filtered');
    }
});

AllView = Backbone.View.extend({
    initialize: function() {
        var eventProxy = {};
        _.extend(eventProxy, Backbone.Events);
        this.newsListView = new NewsListView({eventProxy: eventProxy});
        this.filterView = new FilterView({eventProxy: eventProxy});
    }
});

答案 5 :(得分:0)

使用small backbone.js hack可以解决这个问题。只需修改Backbone.Events.trigger即可将事件传递给this.parent

if this.parent != null