2011-12-14 67 views
4

我使用Backbone與CoffeeScript和Handlebars結合創建搜索結果頁面。我有兩個視圖:一個用於結果列表(ListView),第二個視圖用於單個結果(ResultView)。簡化代碼:將骨幹視圖重新分配給新創建的DOM元素

ListView = Backbone.View.extend 
    el: $("ul#results") 
    ... 

    addItem: (result) -> 
    resultView = new ResultView({ 
     model: result 
    }) 
    resultView.parentView = this 
    this.el.append(resultView.render().el) 

ResultView = Backbone.View.extend 
    tagName: "li" 
    className: "result" 
    events: 
    ... 

簡短說明:

  • ListView控件被分配到ul#results
  • 當結果添加到列表視圖,創建ResultView,有其父的知識和渲染本身
  • 對於ResultView元素li.result被創建(默認主幹行爲)

這是(簡體)我使用呈現搜索結果的模板:

<li class="result"> 
    <h1> 
    <a href="{{link}}">{{title}}</a> 
    </h1> 
    <p>{{snippet}}</p> 
</li> 

這裏是我的難題,你可能已經發現了自己:我定義我的骨幹ResultView在li.result我的模板。我不能做什麼:

  • 綁定ResultView到模板中的li.result,因爲它還沒有在DOM
  • 存在拆除模板中的li.result,因爲我還需要它爲那些沒有啓用JavaScript的頁面渲染頁面服務器端

有沒有一種方法(優雅地)重新分配一個骨幹視圖到一個元素被實例化後?或者簡單地說,我可以引用ResultView到一個臨時元素,渲染模板,然後將它移動到ul#result?或者我以錯誤的方式看待它?

謝謝!

回答

2

我會建議只是從您的視圖觸發事件渲染,然後在onRendered回調執行你的操作,像這樣:

initialize: function() { 
    this.bind('rendered', onRendered); 
}, 

onRendered: function() { 
    // do onRendered stuff 
    // eg. remove an element from the template 
}, 

render: function() { 
    // your render stuff 
    this.trigger('rendered'); 
} 
+0

非常感謝!我實際上將你的答案與Scott Harvey的答案結合起來;我使用渲染觸發器,重新分配我的新`li.result`,然後使用@delegateEvents確保事件被綁定。 – Phortuin 2011-12-20 10:34:58

1

我發現當您嘗試支持服務器端呈現的視圖和客戶端視圖時,事情總是會變得複雜一些。你在這裏描述的場景就是一個很好的例子。

如果可能的話,我會將頁面的渲染移動到客戶端,這將大大簡化您的代碼。

這就是說,如果你確實想保持服務器呈現視圖我可能會執行一個fetch()在頁面加載後從服務器獲取所有對象的集合。然後,您可以調整您的ResultView初始化函數以執行以下檢查。

ResultView = Backbone.View.extend 
    initialize: (attributes) -> 
    exisitingElement = $('result_' + attributes['id']) 
    if exisitingElement? 
     @el = exisitingElement 
     @delegateEvents() 

然後,你會改變你的模板,包括一個唯一的ID。

<li id="result_{{id}}" class="result"> 
     <h1> 
     <a href="{{link}}">{{title}}</a> 
     </h1> 
     <p>{{snippet}}</p> 
    </li> 

這樣,ResultView將在呈現新頁面之前查找現有元素。重新分配@el屬性後,手動調用delegateEvents()可確保您定義的任何事件仍然有效。

+0

感謝您的回覆,但我認爲這並沒有解決我的問題;元素是在渲染後創建的,所以'existingElement'永遠不會發生。但是,也許我想要的東西不能完成(有點趕上22),所以我會檢查你的suggestino無論如何。 thx – Phortuin 2011-12-15 12:55:08