Как я могу «всплывать» события в иерархии Backbone View? - PullRequest
19 голосов
/ 23 февраля 2012

У меня есть базовое приложение со структурой представления, которая выглядит следующим образом - обратите внимание, что для краткости я удалил реализации, модели, коллекции и т. Д.Вызвана функция * toggleFilter(), я хотел бы запустить событие с именем filtered или что-то подобное, которое затем перехватывается NewsListView, который затем вызывает свою функцию reset()Не передавая ссылку на объект NewsListView на мой FilterView, я не уверен, как отправить ему событие.Есть идеи?

Ответы [ 6 ]

5 голосов
/ 24 февраля 2012

Вы на правильном пути. Похоже, вам нужен глобальный диспетчер событий. Здесь приличная статья и пример: http://www.michikono.com/2012/01/11/adding-a-centralized-event-dispatcher-on-backbone-js/

3 голосов
/ 16 августа 2013

Возможно, вы сможете сделать это, используя уже доступную функциональность событий jquery и свойство магистральных событий.

Например, вместо того, чтобы делать это изнутри вашего подпредставления:

this.trigger("yourevent", this);

сделайте это вместо:

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

Затем в любом представлении, которое является родителем, прародителеми т. д. вашего дочернего представления, прослушайте событие в $ el этого представления, определив свойство для объекта событий этого представления:

events:{
    "yourevent":"yourhandler"
}

и определите также обработчик для этого представления:

yourhandler:function(subview) {
}

Таким образом, представлению не нужно знать о том, какие виды-потомки существуют, а только тот тип события, который его интересует. Если представление, инициирующее событие, уничтожается, ничто не должно изменяться в представлении предка.Если представление предка уничтожено, Backbone автоматически отсоединит обработчики.

Предостережение: На самом деле я еще не пробовал это, так что, возможно, где-то там есть ошибка.

1 голос
/ 29 декабря 2015

Самый простой способ запуска и прослушивания событий - просто использовать сам объект Backbone. В него уже включены функции событий, поэтому вы можете просто вызвать, например:

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

затем, в любом другом виде магистрали в вашем приложении , вы можете прослушать это событие, например:

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

Я не совсем уверен, в чем преимущество не в том, чтобы использовать объект Backbone в качестве обработчика событий, а вместо этого создавать отдельный объект для этого, но для быстрой и грязной работы вышеприведенное работает отлично. НТН!

ПРИМЕЧАНИЕ. Одним из недостатков этого является то, что каждый слушатель будет «слышать» каждое событие, инициированное таким образом. Не уверен, что значит «большой О», но будьте осторожны, чтобы не перегружать ваши взгляды множеством подобных вещей. Опять же: это быстро и грязно! :)

1 голос
/ 12 января 2013

Вам следует воспользоваться плагином Backbone.Courier, так как всплывающие события являются идеальным вариантом использования:

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

0 голосов
/ 28 августа 2012

Эту проблему можно решить с помощью небольшого взлома backbone.js.Просто измените Backbone.Events.trigger для передачи событий в this.parent

if this.parent != null
0 голосов
/ 23 февраля 2012

Итак, я нашел решение - создать объект, который расширяет 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});
    }
});
...