2013-03-09 53 views
1

在我Backbone.js的之後,我有以下Backbone.js的返回EL通過異步Ajax調用渲染

class ParentView extends Backbone.View 
    el:"#main" 

    childView : new ChildView 

    render: => 
    $(@el).empty().append(@childView.render().el) 


class ChildView extends Backbone.View 

    render: => 
    $.ajax 
     url:"get_data" 
     success: (data) => 
     $(@el).empty().append("Child View done") 
     @ 

ParentView不顯示任何東西,因爲我覺得孩子視圖的render功能做一個AJAX打電話,父視圖的render並沒有真正「等待」 AJAX來完成。

什麼是實現這一目標的常用方法?

回答

1

正如nl_0的回答說的。你正在從ajax調用返回承諾。你想要返回什麼,或者打算返回@是子視圖實例。對於你如何獲取數據,nl_0也是正確的。你不是真的使用了什麼擅長的,如果你從AJAX獲取數據調用,而不是使用骨幹模型和收集數據層骨幹。因爲這個原因,我要爲他的答案投票,但我希望以下內容能夠幫助解釋這個問題。

發生了什麼事是:

class ParentView extends Backbone.View 
    el:"#main" 

    childView : new ChildView 

    render: => 
    $(@el).empty().append(@childView.render().el) 
    // because of the subtle mistakes in @childView.render() below 
    // your childView never got anything appended to it. 
    // @childView.render().el is undefined 
    // essentially $(@el).empty().append(undefined) 
    // that's why nothing shows up. 


class ChildView extends Backbone.View 

    render: => 
    $.ajax 
     url:"get_data" 
     success: (data) => 
     // @ is not a reference to your child view. 
     // the value of @ has changed context 
     // that means @el is undefined. 
     // You're selecting $(undefined) not your views element. 
     $(@el).empty().append("Child View done") 
     @ // this is not your ChildView instance 

你可以做的是:如果

class ParentView extends Backbone.View 
    el:"#main" 

    childView : new ChildView 

    render: => 
    // this line is actually okay if we fix @childView. 
    $(@el).empty().append(@childView.render().el) 


class ChildView extends Backbone.View 

    onSuccess: (data) => 
    // the double arrow binds this function to the proper context 
    // @ is our ChildView instance 
    @$el.empty().append("GET get_data is done.") 

    render: => 
    $.ajax 
     url:"get_data" 
     success: @onSuccess 

    // return @ out here where it is the instance. 
    // This is really where "Child View done". 
    @ 

抱歉,我犯任何錯誤。我的咖啡腳本很少使用。我認爲這是你的意思。非常微妙的東西,讓我知道如果我需要編輯這個答案。

根據您的Ajax調用需要多長時間,你還可以看到輕微的延遲,因爲childView.render().el將被追加到DOM,Ajax調用回來,並附加之前「獲取GET_DATA就完成了。」

0

實現,這將是如下典型的基幹圖案:

render: => 
    $.ajax 
    url:"get_data" 
    success: (data) => 
     #when the ajax call returns, modify the contents of the view's el 
     @$el.empty().append("Child View done") 

    @ #return this 

基本上你render方法只是揭開序幕Ajax請求,並立即返回控制返回給調用者。當AJAX請求返回時,內容的視圖的被修改,但是視圖的元素不發生變化。

這意味着,當您的父視圖將childView.el附加到它自己的視圖時,childView.render是同步還是異步無關緊要。根元素el存在,無論它是否已經擁有內容:

@$el.empty().append(@childView.render().el) 

同樣重要的是使用view.$el財產,而不是用jQuery選擇($(@el))包裝view.el。前者將作品是否存在於DOM視圖的元素,而後者會失敗,如果父視圖未完全由AJAX請求成功的時候呈現。

1

$.ajax調用是異步的,它返回一個承諾,你render方法返回此承諾。我建議你閱讀一些關於js中的異步性的內容以更好地理解這個概念。

而且要實現通常以某種方式做了這樣的內容:

class ChildView extends Backbone.View 
    initialize: -> 
    @on 'data:fetched', @render 

    render: => 
    @$el.html("Child View done") 
    @ 

    fetch: => 
    $.ajax 
     url: "get_data" 
     success: (data) => 
     # process data and attach it to view 
     @trigger 'data:fetched' 

BTW它被認爲是更好的做法是把所有的數據訪問/操作邏輯放到模型層:模型和集合。在這種情況下,你可以這樣做:

class ChildView extends Backbone.View 
    initialize: -> 
    @collection.on 'reset', @render 
    # call @collection.fetch() somewhere 
    # or use @model.on 'change', @render to bind rendering to model changes 

    render: => 
    @$el.html("Child View done") 
    @