私は backbone.js が初めてで、最初のプロジェクトは、プロジェクト全体で簡単に再利用できるポップオーバー ビューを実装することです。以下の要件を定義しました。
要件
ポップオーバーの位置を計算し、ポップオーバーを開いたり閉じたりできるように、ポップオーバーは DOM 内の別の要素を参照する必要があります。参照はポップオーバー トグル ボタンとして機能します
新しいポップオーバーが本文に追加され、閉じるとポップオーバーが破棄され、DOM から削除されます
ポップオーバーの外側をクリックすると、強制的にポップオーバーが閉じて破棄されます
ポップオーバーはバックボーン ビューであり、その親/作成者ビューから独立している必要があります。開く/閉じるなどの通信は、イベントを使用して実行する必要があります
ポップオーバー コンテンツは別のビューである可能性があります
実装:
まず、ポップオーバー リファレンスとなるビューを作成します。
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();
}
});
次のように見えますが、下層のポップオーバーが多数あります。