2012-06-27 88 views
1

渲染jQuery对象我是相当新的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命中时,items变量不能填充,因为我传递了一个jQuery对象而不是一个字符串,然而无论何时我使用items: this.itemsContainer.html(),只需粘贴由引号括起来的html。 ..我可以简单地更换引号,但只是感觉就像一个黑客给我。

任何帮助将不胜感激。谢谢!

回答

2

jQuery的append不采取的数组:

.append(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); 
     } 
    }, 
    //... 
}); 
+0

哇,感谢伟大的答案!非常丰富和有益的。 我编辑了Github链接,以正确反映我正在工作的来源。我认为,因为这是[jashkanes](https://twitter.com/#!/jashkenas)的工作原理,那么使用'constructor'将会很好。再次感谢详细的回复,队友。 –

+0

@Jaysche:我没有在那里使用'constructor',也许它只是早于Backbone中initialize'的旧代码。使用'$(this.el)'而不是'this。$ el'确实表明它有点老,并且可能没有为更新的Backbones进行更新。 –

+0

我想这是有道理的。我正在读一些有关DocumentCloud的文章,显然Backbone是通过从项目中提取的部分代码创建的,所以这很可能是这里发生的。再次感谢! –