1

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

当我切换页面时,当前页面的全局视图被替换为新页面的视图。在该视图中,我有一个典型的“渲染”功能,它用新模板替换正文 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;
    }
});

谢谢。

4

1 回答 1

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. 浏览器渲染一切,这个过程计算你想要的位置和偏移量。

你只需要让45在7之后发生。

一个简单的方法是将您的位置/大小相关的东西放在_.defer回调中:

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

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

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

于 2013-05-05T17:51:03.193 回答