在呈现Backbone View时收到通知

Cri*_*hai 1 javascript coffeescript backbone.js backbone-views

我正在研究一个Backbone.View应该将集合呈现为可滚动列表的集合.

作为初始渲染的一部分,我需要访问一些布局属性(例如clientWidth),这些属性仅在渲染视图后才可用.

我的问题是,我如何知道何时将视图添加到DOM?


使用a Backbone.View通常有两种方法将视图附加到DOM:

  1. 创建视图>渲染>附加它:

    view = new MyList().render()
    $('#dummy').append(view.$el)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建视图并就地呈现它:

    new MyList({el: '#dummy'}).render()
    
    Run Code Online (Sandbox Code Playgroud)

注意:我知道(1)和(2)不是完全等价的,这不是重点.


让我们考虑我的列表定义如下:

class MyList extends Backbone.View
    render: ->
        @$el->html( ... )
        @

    layout: ->
        max = $el.scrollWidth - $el.clientWidth
        # ... disable / enable scrolling arrows based on max ...
Run Code Online (Sandbox Code Playgroud)

在MyList附加到DOM之后,您如何确保调用layout()?

Jus*_*tin 8

我遇到过这个问题,有些模式可以提供帮助.Backbone为您提供工具,但不会告诉您如何使用它们.在使用它时建立良好的模式非常重要.我使用了两种不同的模式来帮助解决这个问题.

1)根据应用程序的工作方式,在渲染方法并将其附加到DOM后,始终可以轻松或难以确保在视图上调用attached()方法或触发attached事件.就我而言,这很简单,因为我创建了一个架构,我可以在一个中心位置处理它.

2)如果你总是在渲染之后立即将你的元素附加到DOM - 特别是在渲染之后的任何时间,而不是在异步回调中通过这样做来延迟附加,那么在你的render()函数中你可以将调用推迟到layout()或者需要运行什么被附上后 像这样:

var MyList = Backbone.View.extend({
  render: function() {
    /* rendering logic goes here */

    // Notice that the timeout is 0 - you can actually not even pass this argument
    // but I wanted to emphasize that there is no delay given.
    setTimeout(this.layout, 0);

    return this;
  },

  layout: function() {
    // This code won't be run until after this.el is attached to the DOM
  }
});

var view = new MyList().render();
$('#dummy').append(view.$el);
Run Code Online (Sandbox Code Playgroud)

Javascript始终是单线程的.I/O可以异步完成,但实际需要JS引擎时间的任何东西都不能与其他JS代码并行运行.当您在setTimeout()没有最后一个参数或其值的情况下调用时0,它将基本上将其排队,以便在当前执行的代码完成后尽快运行.

如果你遵循一种在调用后很快就会附加到DOM的模式render()- 在当前正在执行的代码完成运行之前的任何时间,并将控制权返回给JS引擎来运行接下来排队的任何内容,你可以利用这一事实.当运行排队的函数setTimeout(func, 0)运行时,您就可以知道您的视图已附加到DOM.请注意,这与事情是_.defer()一样的,但我想为您解释一下.

再次,模式是非常重要的建立.如果你从来没有保持一致并且没有在你的应用程序中建立模式,你就没有任何保证,你就失去了依赖这种机制的能力 - 以及你可能能够建立的其他机制.希望这可以帮助!