1

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

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

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

然而,他的理解是,网络请求应通过路由器处理 URL 更改(取决于更改 URL 的单击,如下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
    }
});

我想知道进行网络请求的主干原因是什么。

4

2 回答 2

2

绝大多数 AJAX 请求应该从主干开始,model或者collection通过backbone.sync函数处理。关键方法是model.fetch()collection.fetch()model.save()

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

解决您的一些具体问题。

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

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

视图可以发出最终会加载数据的事件吗?

是的,这很好。model.fetch()随着应用程序复杂性的增长以及事件发射所允许的解耦是有价值和有保证的,这只是在调用之外才需要的。对于待办事项列表,它通常是矫枉过正的。对于大型应用程序,这可能是一种干净的方法。

每个模型获取都会导致浏览器 URL 发生变化吗?

不。事实上,许多单页应用程序只是永远存在于“/”中。路由到唯一 URL 是可选的。有些应用程序很容易适应它,而另一些应用程序则不然。不要将“应用程序需要数据 X”等同于“浏览器 URL 需要是 X”。这些是正交的。如果用户在总统列表中单击“比尔·克林顿”的视图,并且您想将 URL 更改为“/presidents/clinton”,那么继续并启动一条新路由,这很有意义,但有时您只是想要一些数据而不更改 URL。

总结一下路由器的职责,我认为如下:

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

所以一个典型的路由器方法伪代码可能是:

  • 当 URL 匹配 /presidents/:name 时,响应如下
  • 获取 :name 参数并制作总统模型
  • 实例化一个 PresidentView,将模型传递给它
  • 调用 PresidentView.render() 并将视图的元素交换到整个页面布局中适当位置的 DOM
于 2013-09-27T18:12:47.307 回答
0

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

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

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_;
}
于 2013-09-27T18:22:24.620 回答