Backbone.js 路由器初始化不会立即运行

Posted

技术标签:

【中文标题】Backbone.js 路由器初始化不会立即运行【英文标题】:Backbone.js Router initialization doesn't run immediately 【发布时间】:2012-05-07 23:04:09 【问题描述】:

我的代码如下:

var AppRouter = Backbone.Router.extend(

    _data: null,
    _length: 0,
    _index: null,
    _todos: null,
    _subtodolist: null,
    _subtodos: null,

    routes: 
        "*action": "index",
        "category/:name": "hashcategory"  
    ,

    initialize: function(options)
        var self = this;
        if (this._index === null)
            $.ajax(
                url: 'data/todolist.json',
                dataType: 'json',
                data: ,
                success: function(data) 
                    self._data = data;
                    self._todos = new TodosCollection(data);
                    self._index = new CategoriesView(collection: self._todos);
                    //self._index.render(); 
                
            );
            return this;
        
        return this;
    ,

    index: function()
        this._index.render();
    ,
 ....

但是当我开始时,firebug 控制台面板总是告诉我this._indexindex 函数中为空。我必须在$.ajax success 回调函数的底部使用self._index.render() 来渲染主页(上面已注释掉)。 index 函数似乎在 initialize 函数之前运行。这怎么会发生,我该如何解决?

顺便说一句,在routes中,如果我使用"": "index",它将不起作用。我必须使用"*action": "index"。但我在其他地方了解到默认 url 可能只是空字符串。为什么我不能在这里使用它?

【问题讨论】:

【参考方案1】:

看起来发生这种情况是因为 this._index 仅在 ajax 回调中设置。因为这是异步的,所以不能保证它会在索引事件处理程序触发之前执行。

根据文档,您在初始加载时需要的模型should be bootstrapped。

如果这不可能,构建此代码的一种方法可能是在路由被命中时获取您的数据,并将重置事件绑定到您的视图,例如

var CategoriesView = Backbone.View.extend(
    initialize: function() 
        this.collection.on("reset", this.render);

    ,

    ...

var AppRouter = Backbone.Router.extend(

    _index: null,
    _todos: null,

    routes: 
        "": "index",
        "category/:name": "hashcategory"  
    ,

    initialize: function(options)
        var self = this;

        self._todos = new TodosCollection();
        self._index = new CategoriesView( collection: self._todos );
    ,

    index: function()
        this._todos.fetch();
    ,

您还需要设置您的集合以构建适当的 URL 来请求 data/todolist.json

【讨论】:

在你的代码中,我认为self._todos = new TodosCollection(data); 应该是self._todos = new TodosCollection();,对吧?【参考方案2】:

确实,这里的问题是initialize 在它内部的 ajax 调用被解决之前返回。

您可以在入口点执行以下操作(通常为$.ready()

var self = this,
    p = $.ajax(
    url: 'data/todolist.json',
    dataType: 'json'
);

p.done(function (data) 
    AppRouter = new Backbone.Router(data: data);
    Backbone.history.start( pushState: true );    
);

这将获取路由,然后用它们初始化路由器并启动Backbone.history。显然你不需要在initialize中再次调用ajax,直接使用options中传入的数据即可。

【讨论】:

谢谢伙计,它现在可以工作了。还有一个问题,"category/:name": "hashcategory" 路由似乎永远不会触发。我的 html 中有一个 <a>link,其中有 'href='#/category/num1'attribute。但每次我点击它时,url 都会改变,但没有其他任何反应。我在hashcategory 方法中有一个console.log('started'),但它什么也没打印。你知道为什么吗?【参考方案3】:

您的问题是路线的顺序。路由按顺序进行评估,因此“*action”将始终匹配。

试试:

routes: 
  "category/:name": "hashcategory"
  "*action": "index",

【讨论】:

以上是关于Backbone.js 路由器初始化不会立即运行的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 Backbone.js 路由(或历史记录)自动将参数添加到 GET 请求?

Backbone.js:未达到路由器回调

Backbone.js:查看状态和路由

Backbone.js URL 路由

Backbone.js 路由而不更改 url

使用 Jasmine 监视 Backbone.js 路由调用