2012-06-27 86 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是通過從項目中提取的部分代碼創建的,所以這很可能是這裏發生的。再次感謝! –