ページ内にパネルを作成する動的ウィジェット システムを作成しようとしています。例を 1 つ挙げてみましょう。
Widgets.create({
name : 'menu-site',
title: 'Menu',
content: 'This is my menu!'
});
これは次のようにレンダリングされます。
<section class="widget menu-site">
<h1>Menu</h1>
<article>This is my menu!</article>
</section>
大丈夫ですよね?私はそれを何千回もしました。ただし、内部でビューを使用しようとすると問題が発生します。
var view = new MyCustomView;
Widgets.create({
name : 'custom-panel',
title: 'Custom Panel',
content: view.render().el
});
WidgetView 内で outerHTML を呼び出してコンテンツをレンダリングできますが、それを行うと、MyCustomView 内で宣言されたイベントが機能しません!
誰かがこの問題に直面したことがありますか?
詳細が必要な人のために、これは私の WidgetView コードです:
var Widget = Backbone.Model.extend({
defaults : function() {
return {
title : '',
content : '',
closeable : true
}
}
});
var WidgetList = Backbone.Collection.extend({
url : '/widgets',
model : Widget
});
Widgets = new WidgetList;
var WidgetView = Backbone.View.extend({
tagName : 'section',
className : function() {
return ['widget',' ', this.model.get('name')].join('');
},
template: _.template($('#widget-template').html()),
events : {
"click .close" : "removeWidget"
},
initialize : function() {
this.listenTo(this.model, 'destroy', this.remove);
},
removeWidget : function() {
this.model.destroy();
},
render: function() {
this.$el.append(this.template(this.model.toJSON()));
return this;
},
});
var AppViewport = Backbone.View.extend({
el : $("#widgets"),
events : {
},
initialize : function() {
this.listenTo(Widgets, 'add', this.addNewWidgetView);
},
addNewWidgetView : function(widget) {
var view = new WidgetView({model: widget});
this.$el.append(view.render().el);
}
});
new AppViewport;
あるいは、これに対する別の回避策を考えています..しかし、この問題を理解するのに多くの時間を無駄にしたため、光が見えません!
更新 --------------- 18/01 ---------
いくつかのテストを行い、コードを変更しました。アンダースコア テンプレートを使用する代わりに、WidgetViewLayout を作成し、すべてのテンプレート作業を手動で行いました。
var WidgetView = Backbone.View.extend({
tagName : 'section',
className : function() {
return ['widget',' ', this.model.get('name')].join('');
},
events : {
"click .close" : "removeWidget"
},
initialize : function() {
this.listenTo(this.model, 'destroy', this.remove);
},
removeWidget : function() {
this.model.destroy();
MenuRouterInstance.navigate('');
},
render: function() {
var layout_view = new WidgetViewLayout({model: this.model.toJSON()});
this.$el.append(layout_view.render().el);
return this;
}
});
var WidgetViewLayout = Backbone.View.extend({
tagName : 'div',
render : function() {
var title = this.model.title,
content = this.model.content,
closeable = this.model.closeable || false;
var anchor = this.setupAnchor(closeable),
h1 = this.setupH1(title, anchor),
article = this.setupArticle(content);
this.$el.append(h1);
this.$el.append(article);
return this;
},
setupH1 : function(title, target) {
var element = $('<h1 />');
element.text(title);
element.append(target);
return element;
},
setupAnchor : function(closeable) {
var element = '';
if(closeable == true) {
element = $('<a />');
element.addClass('close');
element.text('(fechar)');
}
return element;
},
setupArticle : function(content) {
var element = $('<article />');
element.append(content);
return element;
}
})
現在は機能しているようですが、ウィジェット内で作成されたビューにはまだ問題があります。
var view = new MyView;
Widgets.create({
name : 'menu',
title: 'My menu',
content: view.render().el
});
MyView が内部に複数の SubView を作成し、model.destroy を呼び出して Subview の Model の 1 つを削除すると、リッスンされたメソッド「this.remove」は、1 つだけを削除するのではなく、すべての SubView を削除してしまいます。最後に、私はこれを行うことを余儀なくされました:
removeit : function(removed_item) {
if(removed_item.get('name') == this.model.get('name')) {
this.remove();
}
},
悪いパターンかどうかはわかりませんが、うまくいきました!誰かがより良いアイデアを持っていれば幸いです!
][`,s