路由器应该负责网络请求吗? (Backbone.js的)

时间:2013-09-27 17:40:21

标签: javascript backbone.js

我在与同事讨论路由器的责任方面存在分歧。在我们的单页面应用程序中,我的印象是通过触发的事件(即Backbone.Events)处理网络请求(AJAX),如下所示:

events : {
    'click a#getUsers' : 'updateModels'
}

updateModels: function() {
    $.ajax(); or this.Model.fetch();
}

但他的理解是网络请求应该通过路由器更改网址(取决于点击更改网址,如a[href="#getThings"],如此:

var App = Backbone.Router.extend({
    routes: {
        "" : "main",
        "thing" : "getThings"
    }

    getThings: function() {
        this.newView = new NewView();
        $.ajax(); // which populates the view with data
    }
});

我想知道做网络请求的主要原因是什么。

2 个答案:

答案 0 :(得分:2)

绝大多数AJAX请求应以主干modelcollection开头,并通过backbone.sync函数处理。关键方法是model.fetch()collection.fetch()model.save()

Backbone非常灵活,只处理一组非常原始的用例,因此有些情况下您需要走出这些边界,但在视图或路由器中对$.ajax的任何调用都是强烈的代码味道MVC失败。

解决您的一些具体问题。

  

视图可以调用model.fetch()来加载数据吗?

是的,这是非常好的和惯用的主干。

  

视图是否会发出最终会加载数据的事件?

是的,这完全没问题。除了调用model.fetch()之外,这只是必要的,因为您的应用程序的复杂性增加,并且事件发出允许的解耦是有价值的和有保证的。对于待办事项列表,它通常是矫枉过正的。对于一个巨大的应用程序,这可能是一个干净的方法。

  

每次模型提取是否会导致浏览器URL发生变化?

没有。事实上,许多单页应用程序只是永远存在于“/”。路由到唯一URL是可选的。有些应用程序很容易适应它,有些应用程序则不那么容易。不要将“应用程序需要数据X”与“浏览器URL需要为X”相提并论。这些是正交的。如果用户在总统列表中单击“Bill Clinton”的视图并且您想要将URL更改为“/ presidents / clinton”,那么请继续并启动新路由,这很有道理,但有时您只是想要一些数据而不改变URL。

总结路由器的职责,我想到如下:

  • 根据URL,应该显示哪个View?
  • 同样基于URL,是否需要提取模型ID并将其实例化为模型实例?
  • 连接并渲染视图

因此典型的路由器方法伪代码可能是:

  • 当URL匹配/ presidents /:name时,响应如下
  • 抓住:name参数并制作总统模型
  • 实例化一个PresidentView,将模型传递给
  • 调用presidentView.render()并将视图的元素交换到整个页面布局中适当位置的DOM

答案 1 :(得分:0)

使用Backbone,你应该让Backbone为你做大部分的ajax请求,这通常不会从你的视图而不是路由器触发。当你可以使用Backbone请求时,我永远不会使用jQuery ajax请求。 this.model.fetch()是获得模型的正确方法。我认为路由器是一种定位页面的方法,但更精细的细节应留给视图。然而,在路由器中的逻辑与视图/集合/模型之间进行选择更多的是艺术而不是科学,我将看看其他Backbone示例以获得更多指导。我认为,在很多情况下,网络请求在视图中处理,因为它更容易。

在回复下面的评论时,每当从服务器返回数据时,Backbone都会使用解析来获取所需的信息,因此重写提取将是一个糟糕的决定。您可以覆盖模型的解析方法以获取所需的信息,仅此而已。即:

var YourModel = Backbone.Model.extend({
    parse: function(response) {
        //You can manipulate the object in other ways as well, 
        //but here's how you'd delete info
        delete response.junk;
        return response;
    }
});

同样,每次执行this.model.save()时,它都会在模型发送到服务器之前使用toJSON(),您也可以覆盖它:

toJSON: function() {
    // default -> return _.clone(this.attributes);
    return _new code here_;
}