2012-06-25 69 views
20

使用Backbone和Marionette,我創建了一個新的佈局,進入我的頁面上的主要內容div。佈局是這樣的:Backbone和Marionette的額外包裝

<div id='dash-sidebar'> 
    <div id='dash-profile'></div> 
    <div id='dash-nav'></div> 
</div> 
<div id='dash-content'></div> 

的問題是,當我呈現佈局,骨幹會自動將其包裝在一個div把它變成主要內容的div像這樣前:

<div id='main-content'>  
    <div> 
    <div id='dash-sidebar'> 
     <div id='dash-profile'></div> 
     <div id='dash-nav'></div> 
    </div> 
    <div id='dash-content'></div> 
    </div> 
</div> 

我知道我可以使用tagName更改元素,但是可以避免將模板完全包裝並直接將其插入頁面上的主內容div中?

回答

13

每個骨幹視圖必須由單個元素表示。你的第一個HTML塊有兩個元素,這就是爲什麼它沒有首先包裝在外部div中就不能被視圖表示。

您是否可以重構您的佈局以包含main-content區域?然後佈局的el將對應於整個外部div。

另一件可以嘗試的方法是使用Backbone.View的setElement()方法來覆蓋外部div的創建,並手動將視圖中元素所需的HTML注入。喜歡的東西:

onRender: function() { 
    this.setElement(/* the HTML you want for your layout */); 
} 

我不知道怎麼樣,如果你HTML中有兩個父元素,而不只是一個通過這樣的工作,但是。

+1

有沒有一種木偶特定的方式來完成這個?我認爲最好只使用'模板'屬性 – streetlight

+0

優秀。我真的不喜歡所有其他答案,我看到說操縱DOM來解決這個問題。爲什麼,只要setElement()? – trusktr

6

UPDATE: Marionette.Layout是骨幹觀點的延伸,所以這是正常的行爲,請參閱骨幹文檔:

的「厄爾尼諾」屬性引用在瀏覽器中創建的DOM對象。 每個Backbone.js視圖都有一個「el」屬性,如果沒有定義,Backbone.js將構造它自己的,它是一個空的div元素。

所以我以前的答案不得不無關,與你的問題,對不起。

更新:

發現在關於這個問題的骨幹github上(至極被關閉作爲wontfix)的issue 546,jashkenas張貼了這個評論,說明爲什麼它是不容易實現:

很大一部分使用Backbone Views的優勢在於它們始終具有其元素 - 是否已呈現模板(許多視圖具有多個 模板),而不管 模板是否可用 - 無論視圖是否存在於DOM或 沒有。

這允許您創建視圖並將其添加到DOM中,以後再渲染, 並確保所有事件都綁定正確(因爲 它們是從view.el中委託的)。

如果你能拿出一個好的策略,允許以具有同時保留上述特點 「完整的」模板...... 然後讓我們談論它 - 但它必須允許根元素 存在而不必呈現模板的內容(可能 依賴於可能直到稍後才能到達的數據),並且它必須允許視圖容易地具有多個模板。

+1

任何一種方法都沒有骰子。設置ID以匹配父元素只是將相同的ID添加到包裝div,所以你有兩個具有相同ID的div。第二種方法無法呈現內容。我試過$('#main-content')和'#main-content',但都沒有運氣。任何其他想法? –

+0

也許你可以看看地區,看看[這篇文章](http://stackoverflow.com/a/10521940/984265) – marcoo

10

EDIT3:警告!此答案可能已過時。我收到了一條評論,說這個答案不再有效,並沒有時間去調查(我個人不使用這種方法)。

我喜歡使用Twitter /引導我的UI庫,並有因爲默認的標籤纏繞(特別是我<tbody>和我<tr> S之間的<div>)的一些問題與表的造型。

經過一番挖掘,我在關於how the View attaches the el的Marionette文檔中發現了一些東西。 Backbone builds the el從各種View屬性,並保持內置的元素是最新的,所以它可以在任何時候呈現。所以我想,如果view.el是父母,爲什麼不只是使用HTML內容?木偶也提供了一種方式create a custom Region

我能夠通過創建一個自定義Region一個覆蓋open函數得到一切運行。這樣我可以指定我想用標籤包裝哪些區域以及哪些區域不包含。在下面的示例代碼片段中,我創建了我的自定義無包裝RegionNowrapRegion),並將其用於我的LayoutMyLayout)中,用於我的<tbody>(我在我的真實程序中創建的視圖創建<tr> s)。

var NowrapRegion = Marionette.Region.extend({ 
    open: function(view){ 
    this.$el.html(view.$el.html()); 
    } 
}); 

var MyLayout = Marionette.Layout.extend({ 
    template: templates.mylayout, 
    regions: { 
    foo: '#foo', 
    columns: '#columns', //thead 
    rows: { selector: '#rows', regionType: NowrapRegion } //tbody 
    } 
}); 

BOOM!當我需要時包裝,當我不需要時包裝。

編輯:這似乎影響events應用於*View級別。我還沒有看過它,但要警告他們似乎沒有被觸發。

無論這是否是「正確」的做法,我都不確定。如果他看到這個,我會歡迎來自@ derick-bailey的任何反饋。

EDIT2: @ chris-neale建議如下,我還沒有驗證,但它似乎很好聽。謝謝!

而不是在視圖中複製html,使用 子節點上的深克隆將維護事件和數據。

var NowrapRegion = Marionette.Region.extend({ 
    open: function(view){ 
    view.$el.children().clone(true).appendTo(this.$el); 
    } 
}); 
+0

轟!我可以吻你.. –

+2

這不應該是木偶的一部分嗎?我的意思是ItemViews應該重用只用於選擇區域的div。 –

+0

我並不反對,它肯定會使我的觀點不那麼冗長。最後,我剛剛結束流程並構建了我的HTML模板以使用默認行爲。這並沒有那麼糟糕。 – clayzermk1

1

我想達到幾乎同樣的事情。我想在我的模板中包含所有HTML標記,並讓Backbone完成剩下的工作。所以我寫了下面的代碼片段,它刪除了額外的'div'。

首先,將tagName設置爲'detect',然後在第一次渲染之後,檢測視圖中第一個元素的tagName。顯然,這隻有在您的模板中提供自己的包裝器時纔有效。

// Single table row inside tbody 
tableRowView = Backbone.Marionette.ItemView.extend({ 
    tagName: 'detect', 
    template: function(data) { 
    return Handlebars.templates['tablerow/single'](data); 
    }, 
    onRender: function() { 
    if (this.tagName == 'detect') 
     this.tagName = this.$el.children().first().prop('tagName').toLowerCase(); 
    this.setElement(this.$el.children(this.tagName)); 
    var $parent = this.$el.parent(this.tagName); 
    if ($parent.length) { 
     this.$el.detach(); 
     this.$el.insertAfter($parent); 
     $parent.remove(); 
    } 
    }, 
    modelEvents: { 
    "change": "render" 
    } 
}); 

模板:

<tr> 
    <td>{{artist}}</td> 
    <td>{{title}}</td> 
    <td>{{length}}</td> 
</tr> 

不過,我只是打得四處這一點 - 如果有人看到任何問題,這種做法可能會導致(性能,內存,殭屍等),我d非常樂意瞭解它們。

順便說一句,這可能很容易打包成一個插件。

+0

你還在使用它嗎?你是否遇到過任何問題?這個解決方案很有趣,但我想知道它的可靠性。它到目前爲止,雖然,thx! – alxscms

+0

爲什麼不只是製作tagName:'tr',然後從模板中刪除包裝?如果您需要向該行添加類或屬性,只需通過Backbone.View的屬性屬性添加它們即可。 –

相關問題