1

在我的 Backbone.js 中,我有以下内容

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 完成。

实现这一目标的常用方法是什么?

4

3 回答 3

1

$.ajaxcall 是异步的,它返回一个 Promise,你的render方法返回这个 Promise。我建议您阅读一些关于 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'

顺便说一句,将所有数据访问/操作逻辑放入模型层被认为是更好的做法:模型和集合。在这种情况下,您可以执行以下操作:

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")
    @
于 2013-03-09T09:16:02.443 回答
1

正如 nl_0 的回答所说。您正在从 ajax 调用返回承诺。您想要返回或打算返回的@是子视图实例。nl_0 对您获取数据的方式也很正确。如果您从 ajax 调用中获取数据,而不是使用 Backbones 模型和集合数据层,那么您并没有真正使用骨干网。因此,我将投票支持他的答案,但我希望以下内容确实有助于解释这个问题。

正在发生的事情是:

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".
    @

对不起,如果我犯了任何错误。我的coffeescript 技能很少使用。我想这就是你的意思。非常微妙的东西,如果我需要编辑这个答案,请告诉我。

根据您的 ajax 调用需要多长时间,您可能仍会看到轻微的延迟,因为childView.render().el将在 ajax 调用返回并附加“GET get_data 完成”之前附加到 dom。

于 2013-03-09T10:28:25.477 回答
0

实现此目的的典型 Backbone 模式如下:

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)

使用属性也很重要,而不是使用 jQuery 选择器 ( )view.$el进行包装。无论视图的元素是否存在于 DOM 中,前者都将起作用,而后者将失败,如果在 ajax 请求成功时父视图尚未完全呈现。view.el$(@el)

于 2013-03-09T09:11:39.270 回答