Подтвердить что ты не робот

Backbone JS: можно ли просматривать триггер обновления в других представлениях?

В моем простом проекте у меня есть 2 вида - представление позиции (Бренд) и приложение. Я добавил функцию, которая позволяет выбирать несколько элементов:

var BrandView = Backbone.View.extend({
...some code...
    toggle_select: function() {
        this.model.selected = !this.model.selected;
        if(this.model.selected) $(this.el).addClass('selected');
        else $(this.el).removeClass('selected');
        return this;
    }
});

var AppView = Backbone.View.extend({
...some code...
    delete_selected: function() {
        _.each(Brands.selected(), function(model){ 
            model.delete_selected();
        });
        return false;
    },
});

Вещь, я хочу знать, сколько элементов выбрано. В этом выборе установки НЕ влияет на модель и, таким образом, не запускает никаких событий. И из концепции MVC я понимаю, что взгляды не должны напрямую разговаривать с другими представлениями. Итак, как AppView знает, что что-то выбирается в BrandViews?

И более конкретно, я AppView, чтобы узнать, сколько элементов было выбрано, поэтому, если выбрано более 1, я показываю меню для множественного выбора.

4b9b3361

Ответ 1

Возможно, вы захотите ознакомиться с этим обсуждением паба/вспомогательных событий Backbone:

http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

Мне нравится добавлять его в качестве глобального механизма событий:

Backbone.pubSub = _.extend({}, Backbone.Events);

Затем в одном представлении вы можете вызвать событие:

Backbone.pubSub.trigger('my-event', payload);

И в другом вы можете слушать:

Backbone.pubSub.on('my-event', this.onMyEvent, this);

Ответ 2

Я использую то, что Адди Османи вызывает шаблон медиатора http://addyosmani.com/largescalejavascript/#mediatorpattern. Вся статья хорошо стоит прочитать.

В основном это менеджер событий, который позволяет вам подписаться и публиковать события. Таким образом, ваш AppView будет индексироваться к событию, то есть "выбран". Затем BrandView опубликует "выбранное" событие.

Причина, по которой мне это нравится, - это позволяет отправлять события между представлениями без непосредственного связывания представлений.

Пример

var mediator = new Mediator(); //LOOK AT THE LINK FOR IMPLEMENTATION

var BrandView = Backbone.View.extend({
    toggle_select: function() {
        ...
        mediator.publish('selected', any, data, you, want);
        return this;
    }
});

var AppView = Backbone.View.extend({
    initialize: function() {
        mediator.subscribe('selected', this.delete_selected)
    },

    delete_selected: function(any, data, you, want) {
        ... do something ...
    },
});

Таким образом, ваше приложение не заботится о том, является ли это BrandView или FooView, который публикует "выбранное" событие, только событие произошло. В результате я нахожу его удобным для пользователя способом управления событиями между частями вашего приложения, а не только представлениями.

Если вы читаете далее о "Фасад", вы можете создать хорошую структуру разрешений. Это позволит вам сказать, что только "AppView" может подписаться на мое "выбранное" событие. Я нахожу это полезным, так как он очень четко показывает, где используются события.

Ответ 3

Игнорируя проблемы, о которых вы уже упоминали в своем сообщении, вы можете связывать и запускать события в/из глобального объекта Backbone.Event, что позволит что-либо говорить со всем остальным. Определенно, это не лучшее решение, и если у вас есть представления, общающиеся друг с другом, вам следует подумать об их рефакторинге. Но вот иди! Надеюсь, это поможет.

Ответ 4

Вот мой случай с аналогичной потребностью: Backbone listenTo выглядел как решение для перенаправления на страницу входа в систему для отложенных или не прошедших проверку подлинности запросов.

Я добавил обработчик событий на свой маршрутизатор и заставил его прослушивать глобальное событие, например:

 
Backbone.Router.extend({
    onNotAuthenticated:function(errMsg){
        var redirectView = new LoginView();
        redirectView.displayMessage(errMsg);
        this.loadView(redirectView);
    },
    initialize:function(){
        this.listenTo(Backbone,'auth:not-authenticated',this.onNotAuthenticated);  
    },
    .....
});

и в моем обработчике ошибок jquery ajax:

$(document).ajaxError(
    function(event, jqxhr, settings, thrownError){
        .......
        if(httpErrorHeaderValue==="some-value"){
             Backbone.trigger("auth:not-authenticated",errMsg);
        }
    });     

Ответ 5

Вы можете использовать объект Backbone в качестве шины событий.

Этот подход несколько более чист, но по-прежнему полагается на объект Global Backbone, хотя

var view1 = Backbone.View.extend({

  _onEvent : function(){
    Backbone.trigger('customEvent');
  }

});


var view2 = Backbone.View.extend({

  initialize : function(){
    Backbone.on('customEvent', this._onCustomEvent, this);
  },

  _onCustomEvent : function(){
    // react to document edit.
  }

});

Ответ 6

Использовать те же объекты модели. AppView может быть инициализирован коллекцией, а BrandView инициализируется одной моделью из этой коллекции. Когда атрибуты объекта ветвления меняются, любой другой код, который имеет ссылку на эту модель, может прочитать его.

Так что давайте так получим некоторые бренды, которые вы получаете через коллекцию:

var brands = new Brands([]);
brands.fetch();

Теперь вы создаете AppView и массив BrandView для каждой модели.

var appView = new AppView({brands: brands});
var brandViews = brands.map(function(brand) {
  return new BrandView({brand: brand});
});

Теперь appView и brandViews имеют доступ к тем же объектам модели, поэтому при изменении одного из них:

brands.get(0).selected = true;

Затем он изменяется при обращении к представлениям, которые также ссылаются на него.

console.log(appView.brands.get(0).selected); // true
console.log(brandViews[0].brand.selected)    // true

Ответ 7

Как и Джон предложил выше, шаблон посредника работает очень хорошо в этом сценарии, поскольку Адди Османи суммирует эту проблему снова в Основы основы > .

Поврежден, используя плагин Backbone.Mediator, который прост и велик, и делает мои модули просмотра AMD совместимыми без проблем =)