我是Backbone.js开发的新手,在尝试渲染子视图时遇到了一些障碍。
目前,我已经有几个视图来呈现自定义下拉按钮以及其他元素。我基于DocumentCloud's code
采用了这种方法这是我到目前为止所拥有的:
app.ui.SelectMenu = Backbone.View.extend({
className: 'btn-group group-item',
options: {
id: null,
standalone: false
},
events: {
"click .dropdown-menu a": "setLabel"
},
constructor: function (options) {
Backbone.View.call(this, options);
this.items = [];
this.content = JST['common-select_button'];
this.itemsContainer = $('.dropdown-menu', $(this.content.render()));
// Add any items that we may have added to the object params
if (options.items) {
this.addItems(options.items);
}
},
render: function () {
this.$el.html(this.content.render({
label: this.options.label,
items: this.itemsContainer
}));
this._label = this.$('.menu-label');
return this;
},
setLabel: function (label) {
$(this._label).text(label || this.options.label);
},
addItems: function (items) {
this.items = this.items.concat(items);
var elements = _(items).map(_.bind(function (item) {
var attrs = item.attrs || {};
_.extend(attrs, { 'class': 'menu_item' + (attrs['class'] || '') });
var el = this.make('li', attrs, item.title);
return el;
}, this));
$(this.itemsContainer).append(elements);
}
});
到目前为止,我已成功渲染了我的按钮以及相应的标签,但在调用.dropdown-menu
函数时似乎无法填充addItems
。
我假设当render
命中时,由于我传递的是jQuery对象而不是字符串,因此无法填充items变量,但每当我使用items: this.itemsContainer.html()
时,只是粘贴引号括起来的html ...我可以简单地替换引号,但这对我来说就像是一个黑客。
非常感谢任何帮助。谢谢!
答案 0 :(得分:2)
jQuery的append
不接受数组:
<强>
.append( content [, content] )
强>content :要在匹配元素集中的每个元素末尾插入的DOM元素,HTML字符串或jQuery对象。
内容:要在匹配元素集中的每个元素的末尾插入的一个或多个其他DOM元素,元素数组,HTML字符串或jQuery对象。
如果要在一次调用中追加多个元素,则必须将它们作为单独的参数提供:
$(x).append(e1, e2, e3, ...);
因此您必须使用apply
将数组转换为单独的参数:
var $i = $(this.itemsContainer);
$i.append.apply($i, elements);
虽然这种诡计并非必要,但您可以在创建时逐一添加它们:
addItems: function (items) {
this.items = this.items.concat(items);
_(items).each(function (item) {
var attrs = item.attrs || {};
_.extend(attrs, { 'class': 'menu_item' + (attrs['class'] || '') });
this.itemsContainer.append(this.make('li', attrs, item.title));
}, this);
}
另请注意,_.each
可以使用context
参数,因此您无需单独_.bind
次呼叫。而且我很确定this.itemsContainer
已经是一个jQuery对象,所以你不需要再次包装$()
。
您的render
也可能出现问题:
render: function () {
this.$el.html(this.content.render({
label: this.options.label,
items: this.itemsContainer
}));
this._label = this.$('.menu-label');
return this;
}
我怀疑items: this.itemsContainer
将结束字符串this.itemsContainer
,你可能会有更好的运气:
this.$el.html(this.content.render({ label: this.options.label });
this.$el.find('some selector').append(this.itemsContainer);
其中'some selector'
当然取决于HTML结构;你也必须为此调整模板。
您的Github链接已损坏,因此我不知道您正在调整哪些代码。我知道您对constructor
的使用是非标准的。为什么不使用标准initialize
?
构造函数/初始化
new View([options])
[...]如果视图定义了
initialize
函数,则在首次创建视图时将调用它。
你应该这样做:
app.ui.SelectMenu = Backbone.View.extend({
// No 'constructor' in here or anywhere...
initialize: function (options) {
this.items = [];
this.content = JST['common-select_button'];
this.itemsContainer = $('.dropdown-menu', $(this.content.render()));
// Add any items that we may have added to the object params
if (options.items) {
this.addItems(options.items);
}
},
//...
});