如何在主干视图层次结构中"bubble up"事件?



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

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();
    }
});

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

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

您可以使用 jquery events 的现有功能和 backbone events 属性来执行此操作。

例如,不是从子视图中执行此操作:

this.trigger("yourevent", this);

请改为执行以下操作:

this.$el.trigger("yourevent", this);
然后,在作为子视图的父视图

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

events:{
    "yourevent":"yourhandler"
}

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

yourhandler:function(subview) {
}
因此,这样,视图就

不需要知道存在哪些后代视图,只需要知道它感兴趣的事件类型。 如果发起事件的视图被销毁,则无需更改上级视图的任何内容。 如果祖先视图被销毁,Backbone 将自动分离处理程序。

警告:我还没有真正尝试过这个,所以可能在某个地方有一个陷阱。

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

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

我发现触发和侦听事件的最简单方法是使用 Backbone 对象本身。它已经混合了事件函数,因此您只需触发例如:

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

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

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

我不完全确定不使用 Backbone 对象作为事件处理程序,而是创建一个单独的对象来执行此操作有什么好处,但对于快速而肮脏的工作,上述工作正常。哼!

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

这个问题

可以用小骨干来解决.js黑客。只需修改 Backbone.Events.trigger 即可将事件传递到this.parent

if this.parent != null

所以,我想出了一个解决方案 - 创建一个扩展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});
    }
});

最新更新