如何在Backbone.js中插入后再次准备好DOM

时间:2013-05-05 17:05:31

标签: javascript dom backbone.js

我正在使用Backbone.js开发一个应用程序。

当我切换页面时,当前页面的全局视图将替换为新页面的视图。在该视图中,我有一个典型的“渲染”功能,可以用新模板替换body html。

我的问题是,在更改了html,所以DOM之后,如何在DOM再次准备好后执行函数?

我必须使用它,因为我需要滚动到一个元素,并在render()不起作用后执行我的scrollTo()函数($(myElement).offset()。top总是返回0)。

这是我的代码:

module.exports = BaseView.extend({
    initialize: function () {
        this.render();
        $('html, body').scrollTop(this.$("#toScroll").offset().top);
    },
    template: require('./templates/home'),
    render: function () {
        this.$el.html(this.template());
        return this;
    }
});

感谢。

1 个答案:

答案 0 :(得分:5)

如果您的视图el位于DOM中,并且您的#toScroll位于视图的el内,那么只要您这样说,#toScroll就会出现在DOM中:

this.$el.html(this.template());

但是,在浏览器再次获得控制权之后(即在您的视图完成所有工作之后),HTML才会呈现。 el内的元素在浏览器渲染完所有内容之前不会有任何大小或位置信息(当然,除非您手动定位和调整所有内容)。事件的顺序如下:

  1. v = new View
  2. initialize被调用,并调用render
  3. render设置DOM中的所有内容。
  4. 视图调用this.$('#toScroll').offset()并获取零。
  5. 视图尝试scrollTop为零。
  6. 浏览器获得控制权。
  7. 浏览器呈现所有内容,此过程会计算您想要的位置和偏移量。
  8. 您只需要在 7 之后获得 4 5

    一种简单的方法是将您的位置/尺寸依赖的内容放在_.defer回调中:

    initialize: function () {
        this.render();
        var _this = this;
        _(function() {
            $('html, body').scrollTop(_this.$("#toScroll").offset().top);
        }).defer();
    }
    

    您也可以使用延迟为零的setTimeout,但_.defer会让您的意图更加清晰。

    演示:http://jsfiddle.net/ambiguous/tWSBE/