2011-10-04 147 views
7

我在圈子裏跑來跑去,似乎在我當前的應用程序中實施backbone.js中缺少一些東西。問題是我有一個主AppView,它初始化頁面的各種子視圖(圖表,信息表等)。我的願望是能夠根據導航時傳遞的參數標誌更改頁面的佈局。骨幹視圖嵌套

我碰到的情況是,在模板渲染後引用了dom元素的子視圖在主AppView初始化過程中無法訪問這些元素。所以主要的問題是如何確保適當的dom元素適用於每個事件綁定過程以正確設置?

如果我有一個事件綁定到我的LayoutView中的模型更改,則會顯示佈局,但後續視圖無法正確呈現。我已經弄清楚的一些事情是將所有視圖的'.el'值設置爲html結構中的靜態元素。這會使渲染髮生,儘管這似乎脫離了利用'.el'提供的良好範圍限制能力。

示例代碼:

//Wrapped in jquery.ready() function... 
//View Code 
GraphView = Backbone.View.extend({ // init, model bind, template, supporting functions}); 

TableView = Backbone.View.extend({ // init, model bind, template, supporting functions}); 

LayoutView = Backbone.view.extend({ 
    initialize: function() { 
    this.model.bind('change:version', this.render, this); 
    }, 
    templateA = _.template($('#main-template').html()), 
    templateB = _.template($('#secondary-template').html()), 
    render: function() { 
    if ('main' == this.model.get('version')) { 
     this.el.html(this.templateA()); 
    } else { 
     this.el.html(this.templateB()); 
    } 
    }, 
}); 

MainView = Backbone.View.extend({ 
    initialize: function() { 
    this.layoutView = new LayoutView({ 
     el: $('#layoutContainer'), 
     model: layout, 
    }); 
    this.graphView = new GraphView({ 
     el: $('.graphContainer'), 
     model: graph 
    }); 
    this.tableView = new TableView({ 
     el: $('#dataTableContainer', 
     model: dataSet 
    }); 
    }, 
}); 

// Model Code 
Layout = Backbone.Model.extend({ 
    defaults: { 
    version: 'main', 
    }, 
}); 

Graph = Backbone.Model.extend({}); 
dataSet = Backbone.Model.extend({}); 

// Router code... 

// Fire off the app 
AppView = new MainView($('#appContainer')); 
// Create route, start up backbone history 

HTML: 爲簡單起見我只是重新安排了兩個佈局之間的div。

<html> 
    <head> 
    <!-- include above js and backbone dependancies --> 
    </head> 
    <body> 
    <script type="text/template" id="main-template"> 
     <div class="graphContainer"></div> 
     <div class="dataTableContainer"></div> 
     <div>Some other stuff to identify that it's the main template</div> 
    </script> 
    <script type="text/template" id="secondary-template"> 
     <div class="dataTableContainer"></div> 
     <div>Rock on layout version two!</div> 
     <div class="graphContainer"></div> 
    </script> 
    <div id="appContainer"> 
     <div id="nav"> 
     <a href="#layout/main">See Layout One</a> 
     <a href="#layout/secondary">See Layout Two</a> 
     </div> 
     <div id="layoutContainer"></div> 
    </div> 
    </body> 
</html> 

感謝您對任何人都有的見解/意見。謝謝!

+0

只是FYI,你的代碼中有一堆拼寫錯誤 - 假設它們是複製/粘貼問題,而不是實際的語法錯誤,是否安全? – nrabinowitz

+0

責備複製/粘貼,基本的邏輯,希望仍然被傳達。感謝您指出了這一點。 – aztechy

回答

8

您的示例中有很多缺少的代碼,但是如果我理解正確,則問題在於您嘗試渲染依賴於由LayoutView生成的HTML的視圖,但是在使用時會不同步地選擇佈局模型已更新,因此LayoutView尚未呈現。

有(與幾乎所有骨幹相關的)多種方法來此,但一般:

  • 如果我有誰依賴於一個「父」的觀點被渲染的意見,我會把這些視圖的實例化和渲染的責任放在父視圖中 - 在這種情況下,LayoutView,而不是MainView

  • 如果父項異步渲染,則需要在回調中執行該實例 - 這裏是LayoutView.render()方法。

,所以我可能構建這樣的代碼:

LayoutView = Backbone.view.extend({ 
    initialize: function() { 
    this.model.bind('change:version', this.render, this); 
    // you probably want to call this.model.fetch() here, right? 
    }, 
    templateA: _.template($('#main-template').html()), 
    templateB: _.template($('#secondary-template').html()), 
    render: function() { 
    if ('main' == this.model.get('version')) { 
     this.el.html(this.templateA()); 
    } else { 
     this.el.html(this.templateB()); 
    } 
    // now instantiate and render subviews 
    this.graphView = new GraphView({ 
     // note that I'm using this.$ to help scope the element 
     el: this.$('.graphContainer'), 
     model: graph 
    }); 
    this.tableView = new TableView({ 
     el: this.$('.dataTableContainer'), 
     model: dataSet 
    }); 
    // you probably need to call graphView.render() 
    // and tableView.render(), unless you do that 
    // in their initialize() functions 
    }, 
}); 

請注意,您不必在el通過在實例化 - 你可以在initialize()實例子視圖,並設置el屬性在subview.render()。您可以像現在這樣在MainView.initialize()中實例化,並將視圖傳遞給LayoutView以異步渲染。但我認爲上述方法可能更清潔。

+0

感謝您的回覆。我在渲染過程完成後調用了LayoutView中的子視圖。假設各種子視圖都有自己的渲染,這些渲染在模型更改狀態中更新,這是正確的。 由於某些奇怪的原因,儘管它在我的抓取後似乎有些渲染調用被多次調用。引發我認爲我多次無效地添加各種子視圖。我想我可能只需要在獲取我的數據後追蹤其他可能導致多個呈現調用的內容。 再次感謝! – aztechy

+0

很高興這有幫助 - 我經常發現,我需要邏輯來實例化一個子視圖,只有在尚未加載時,這可能是問題。 (順便說一句,如果你喜歡這個答案,你可以通過點擊左邊的複選標記來批准它:) – nrabinowitz

+0

對,需要創建邏輯來實例化子視圖。我不幸遇到了一個問題,即在layoutView.render()中實例化子視圖導致在其初始化設置中定義的模型更改事件上鍵入的子視圖無法正確呈現。主要是在視圖的模型狀態在導航中保持不變的情況下,由於上述過程,該特定子視圖似乎被空模板覆蓋。我認爲這可能需要重新處理事件邏輯。 – aztechy