我试图创建一个动态的Widget系统来在我的页面中创建面板。让我们举一个例子:
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
}); 我可以通过在outerHTML中调用WidgetView来呈现内容,但是,当我这样做时,在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;或者,也许,我在考虑另一个解决办法。但是我浪费了太多的时间去理解这个问题,以至于我看不到光明!
更新
我做了一些测试,并修改了代码:我没有使用下划线模板,而是创建了一个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;
}
})它现在似乎有效了,但是我在Widget中创建的视图仍然存在一些问题,比如:
var view = new MyView;
Widgets.create({
name : 'menu',
title: 'My menu',
content: view.render().el
}); 当MyView在自身内创建多个SubViews时,我调用model.destroy来删除Subview的一个模型,侦听方法"this.remove“最终会删除所有SubViews,而不是只删除一个SubViews。最后,我被迫这样做:
removeit : function(removed_item) {
if(removed_item.get('name') == this.model.get('name')) {
this.remove();
}
},我不知道这是不是一个坏的模式,但它已经成功了!如果有人有更好的主意我很感激!
[`,s
发布于 2013-01-16 03:15:49
我认为您的问题是,您试图将DOM元素对象(el)视为字符串。当你这样做时:
content: view.render().el在content中将有一个活动的DOM节点,视图的事件将绑定到该DOM节点。您可以使用其中一个HTML方法(在您的示例中是outerHTML )通过模板获取节点的HTML,但是处理事件的delegate绑定到DOM节点,而不是绑定到最终使用的HTML字符串。
您可以修改一下您的render以处理原始DOM节点,在必要时可以这样做。
render: function() {
var json = this.model.toJSON();
if(_(json.content).isString()) {
this.$el.append(this.template(json));
}
else {
var content = json.content;
delete json.content;
this.$el.append(this.template(json));
this.$('article').append(content);
}
}基本上,如果您的content不是字符串,那么就手动将其放入$el中,而不是遍历模板。
https://stackoverflow.com/questions/14350651
复制相似问题