admin管理员组

文章数量:1193347

I have a backbone app with a view structure that looks like the following - note that I've removed implementations, models, collections, etc. for brevity:

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

    }

});

Essentially, whenever the FilterView's toggleFilter() function is called, I would like to fire off an event called filtered or something like that that is then caught by the NewsListView, which then calls its reset() function. Without passing a reference of a NewsListView object to my FilterView, I'm not sure how to send it an event. Any ideas?

I have a backbone app with a view structure that looks like the following - note that I've removed implementations, models, collections, etc. for brevity:

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

    }

});

Essentially, whenever the FilterView's toggleFilter() function is called, I would like to fire off an event called filtered or something like that that is then caught by the NewsListView, which then calls its reset() function. Without passing a reference of a NewsListView object to my FilterView, I'm not sure how to send it an event. Any ideas?

Share Improve this question edited Feb 23, 2012 at 0:15 rybosome asked Feb 22, 2012 at 23:54 rybosomerybosome 5,1267 gold badges47 silver badges64 bronze badges
Add a comment  | 

6 Answers 6

Reset to default 5

You're on the right track. It sounds like what you need is a global event dispatcher. There a decent article and example here: http://www.michikono.com/2012/01/11/adding-a-centralized-event-dispatcher-on-backbone-js/

You might be able to do this using the already available functionality of jquery events and the backbone events property.

For example, instead of doing this from inside your subview:

this.trigger("yourevent", this);

do this instead:

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

Then in any view that is a parent, grandparent, etc of your child view, listen for the event on that view's $el by defining a property on that view's events object:

events:{
    "yourevent":"yourhandler"
}

and define the handler on that view as well:

yourhandler:function(subview) {
}

So this way, a view doesn't need to know about what descendant views exist, only the type of event it is interested in. If the view originating the event is destroyed, nothing needs to change on the ancestor view. If the ancestor view is destroyed, Backbone will detach the handlers automatically.

Caveat: I haven't actually tried this out yet, so there may be a gotcha in there somewhere.

You should check out the Backbone.Courier plugin as bubbling events is a perfect use case:

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

The easiest way I've found to trigger and listen to events is to just use the Backbone object itself. It already has the events functions mixed in to it, so you can just trigger eg:

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

then, in any other backbone view in your app, you can listen for this event eg:

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

I'm not exactly sure what the advantage is in not using the Backbone object as your event handler, and instead creating a separate object to do it, but for quick-and-dirty work, the above works fine. HTH!

NOTE: one disadvantage to this is that every listener will "hear" every single event triggered in this way. Not sure what the big O is on that, but work being careful to not overload your views with lots of this stuff. Again: this is quick and dirty! :)

This problem can be solved using small backbone.js hack. Simply modify Backbone.Events.trigger for passing events to the this.parent

if this.parent != null

So, I came up a with a solution - create an object that extends Backbone.Events, and pass it as a parameter to multiple views. This almost feels like message passing between actors, or something. Anyway - I'm posting this as an answer in case anybody else needs a quick solution, but I'm not going to accept the answer. This feels hacky. I'd still like to see a better solution.

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

本文标签: javascriptHow can I quotbubble upquot events in a Backbone View hierarchyStack Overflow