2

私は backbone.js が初めてで、最初のプロジェクトは、プロジェクト全体で簡単に再利用できるポップオーバー ビューを実装することです。以下の要件を定義しました。

要件

  1. ポップオーバーの位置を計算し、ポップオーバーを開いたり閉じたりできるように、ポップオーバーは DOM 内の別の要素を参照する必要があります。参照はポップオーバー トグル ボタンとして機能します

  2. 新しいポップオーバーが本文に追加され、閉じるとポップオーバーが破棄され、DOM から削除されます

  3. ポップオーバーの外側をクリックすると、強制的にポップオーバーが閉じて破棄されます

  4. ポップオーバーはバックボーン ビューであり、その親/作成者ビューから独立している必要があります。開く/閉じるなどの通信は、イベントを使用して実行する必要があります

  5. ポップオーバー コンテンツは別のビューである可能性があります

実装:

まず、ポップオーバー リファレンスとなるビューを作成します。

My.Views.Toggle = Backbone.View.extend({
    tagName: 'a',
    events: {
      'click': 'toggle'
    },
    serialize: function() {
      return { model: this.model };
    },        
    initialize: function() {          
      this.listenTo(this.model, 'change', this.render);
    },
    afterRender: function() {
      //here we should add the popover, right?
    },
    toggle: function(){  
      app.vent.trigger('my:navbar:toggle');
    }
});

上記の実装では、要件 4 を尊重します。ここで、#1 について考えなければなりません。papover にその親ビューの参照を与えることができるようにするには、親のレンダリングが完了するまで待つ必要がありますよね? そのため、afterRender 関数内にポップオーバーを作成する必要があります。

var popover = new Popover.Views.Default({ 
    content: "Hey there, I am a popover", 
    reference: this.$el
});

これの問題は、要件 2 に違反していることです。afterRender 関数が 2 回呼び出されるため、前後でモデルが変更されます。モデルが再び変更されるたびに、この関数も呼び出されます。そのため、DOM にはポップオーバーのインスタンスが多数存在します。

私の質問は、DOM にポップオーバー インスタンスが 1 つしかないことをどのように保証できるかということです。

My.Views.Popover = Backbone.View.extend({
    className: 'popover',
    initialize: function(options) {
      this.visible = false;
      this.content = options.content;
      this.reference = options.reference;

      app.vent.on('member:navbar:toggle', this.toggle, this);

      this.render();
    },
    afterRender: function() { 
      $('body').append(this.$el.append(this.content));
    },
    show: function() {
      this.visible = true;
      this.$el.show(); 
    },
    hide: function() {
      this.visible = false; 
      this.$el.hide();
    },
    toggle: function() {
      this.visible ? this.hide() : this.show();
    }
});

次のように見えますが、下層のポップオーバーが多数あります。

ここに画像の説明を入力

4

1 に答える 1

2

これは非常に独断的な質問なので、私が何をするかを言います。

まず、本体を処理するメイン ビューが必要です。つまりAppView({el:'body'})、アプリケーションをブーストし、その中に入るすべてのビューをレンダリングするのはこのビューです。

第二に、

afterRender: function() { 
  $('body').append(this.$el.append(this.content));
},

ビューは、それが作成された目的に対してのみ責任を負うべきだと思います。それを適切に管理するには、別のビューが実際にその配置と管理を行う必要があります。もちろん、本体を含むメイン ビューを除いて、

My.Views.AppView = Backbone.View.extend({
  el: 'body',
  initialize : function(){
    this.popup = new Popover(...);
  },
  render : function(){
    this.titlebar.render()...
    this.content.render()...
    ...
    this.popup.render().appendTo(this.$el)...;
  }
});

これにより、ビューとその責任の明確な構造が得られると思います。

于 2013-07-07T17:16:06.643 に答える