web-dev-qa-db-ja.com

バックボーンJS:1つのビューで他のビューの更新をトリガーできますか?

単純なプロジェクトでは、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 '); 
これを返す; 
} 
}); 
 
 var AppView = Backbone.View.extend({
 ...一部のコード... 
 delete_selected:function(){
 _.each(Brands.selected()、function(model){
 model.delete_selected() ; 
}); 
 falseを返す; 
}、
}); 

つまり、選択されているアイテムの数を知りたいのです。このセットアップでは、選択はモデルに影響しないため、イベントは発生しません。また、MVCの概念から、ビューが他のビューと直接対話してはならないことを理解しています。では、AppViewは、BrandViewsで何かが選択されていることをどのようにして知ることができますか?

より具体的には、選択されたアイテムの数を知るためにAppViewを使用するため、複数選択された場合は、複数選択用のメニューを表示します。

45
mvbl fst

Backbone pub/subイベントのこのディスカッションを読むことをお勧めします。

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

グローバルイベントメカニズムとして追加するのが好きです。

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

次に、1つのビューでイベントをトリガーできます。

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

そして、別のもので聞くことができます:

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

Addy Osmaniがメディエーターパターンと呼ぶものを使用します 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」のみが「選択した」イベントにサブスクライブできると言うことができます。これは、イベントがどこで使用されているかを非常に明確にするので便利です。

7
John McKim

同様のニーズを持つ私のケースを次に示します。BackbonelistenToは、タイムアウトしたリクエストまたは認証されていないリクエストに対してログインページにリダイレクトするソリューションのように見えました。

ルーターにイベントハンドラーを追加し、次のようなグローバルイベントをリッスンさせました。

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

投稿で既に言及しているこれに関する問題を無視して、グローバルBackbone.Eventオブジェクトへ/からイベントをバインドおよびトリガーできます。間違いなく最善の解決策ではありません。互いにチャットしているビューがある場合は、リファクタリングを検討する必要があります。しかし、そこに行く!お役に立てれば。

1
soundslikeneon

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.
  }

});
1
francesca

ジョンが上記で提案したように、メディエーターパターンはこのシナリオで非常にうまく機能します。AddyOsmaniが Backbone基本 でこの問題を再び要約しているためです。

Backbone.Mediator プラグインを使用して終了します。このプラグインはシンプルで優れており、AMD Viewモジュールがシームレスに連携します=)

0
gsklee

同じモデルオブジェクトを使用します。 AppViewはコレクションで初期化でき、BrandViewはそのコレクションの1つのモデルで初期化できます。ブランチオブジェクトの属性が変更されると、そのモデルへの参照を持つ他のコードはそれを読み取ることができます。

それでは、コレクションを介して取得するいくつかのブランドを手に入れましょう。

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
Alex Wayne