2012-04-02 3 views
44

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

 
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, я показываю меню для множественного выбора.

+2

BTW, '$ (this.el) .toggleClass ("выбрано")'. Или еще короче - this.model.selected = $ (this.el) .toggleClass ('selected "). HasClass (" selected ");' . –

ответ

71

Вы могли бы хотеть иметь чтение этого обсуждения 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); 
+0

На самом деле это именно то, что я читал в конце концов http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/ и начал использовать его. Хорошо. Спасибо. –

+0

Это действительно помогло мне Большое спасибо. – Bharat

+0

Ditto комментарий выше .. большое спасибо! – Alex

1

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

7

Я использую то, что Адди Османи называет схемой медиатора 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» может подписаться на мое «выбранное» событие. Я нахожу это полезным, поскольку он очень четко показывает, где используются события.

+0

Является ли это изначально поддерживаемым в Backbone? –

+0

Это не часть Backbone. , поэтому мне это нравится. Если бы вы связали событие DOM в одном представлении напрямую с другим представлением, которое будет очень запутанным, когда вы пытаетесь изменить свои взгляды. Я обновлю свой ответ, чтобы попытаться выяснить, что я имею в виду. –

0

Используйте те же объекты модели. 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 
+0

ваши первые 2 примера кода уже используются, и я знаю, как получить количество выбранных брендов. Вопрос был, как один вид Знайте, что что-то было выбрано/не выбрано в другом представлении. –

0

То же, что Джон предложил выше, Посредник Pattern работает очень хорошо в этом случае, как и Addy Osmani суммируя этот вопрос снова в Backbone fundamentals.

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

1

Вот мой случай с подобной необходимостью: 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); 
     } 
    });  
+0

На месте, где Backbone.on() не работает this.listenTo() работал ... –

1

Вы можете использовать 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. 
    } 

}); 
Смежные вопросы