1

所以我希望在我超酷的 can.js 应用程序中创建一些路由。目标是这样的……</p>

#!claims          ClaimsController - lists claims

#!claims/:id      ClaimController - views a single claim
#!claims/new      ClaimController - creates a new claim
#!claims/:id/pdf  - do nothing, the ClaimController will handle it

#!admin           AdminController - loads my Administrative panel with menu
#!admin/users     - do nothing, the AdminController will handle it
#!admin/settings  - do nothing, the AdminController will handle it

那么我们该怎么做呢?

“claims route”:      function() { load('ClaimsController'); },
“claims/:id route”:  function() { load('ClaimController'); },
“admin”:             function() { load(‘AdminController’); },

酷豆,我们走了。那么,如果有人将链接发送给类似...

http://myapp#!claims/1/pdf

什么都没发生!好的,让我们添加路线。

“claims/:id/pdf route”: function() { load('ClaimController'); },

伟大的。现在该链接有效。在这里,路由器的工作只是加载控制器。控制器将识别出需要 pdf 操作,并显示正确的视图。

所以假装我已经加载了一个声明claims/:id,我编辑了一两件事。然后我单击打印预览按钮查看 PDF 并将我的路线更改为claims/:id/pdf.

应该发生什么……索赔控制器正在观察路线并显示 pdf 视图。

实际发生了什么……路由器看到更改,匹配claims/:id/pdf我们添加的路由,并重新加载声明控制器,显示从服务器/缓存中提取的声明的新版本,丢失我的更改。

为了尝试定义问题,我需要路由器识别路由何时更改,路由属于哪个控制器,如果控制器已经加载,请忽略它。但这很难!

claims      //
claims/:id // different controllers!

claims/:id      //
claims/:id/pdf // same controller!

我们可以绑定“控制器”更改。所以定义路由can.route(':controller')和绑定在:controller.

{can.route} controller
// or
can.route.bind('controller', function() {...})

但是点击一个声明(从 ClaimsController 更改为 ClaimController)不会触发,因为claim在这两种情况下第一个标记是相同的。

有没有我可以依赖的约定?我是否应该指定应用程序中的每条路由并检查控制器是否已加载?我的首选路线网址不起作用吗?

4

1 回答 1

5

以下是我在复杂的 CanJS 应用程序中设置路由的方法。你可以在这里看到一个例子。

首先,不要使用 can.Control 路由。这是一种反模式,将在 3.0 中删除,类似于本期中的想法。

相反,您设置一个模块,该模块按照与此处使用routing app类似的约定导入和设置模块。

稍后我将解释如何设置routing app模块。但首先,重要的是要了解can.route与您可能习惯于考虑路由的方式有何不同。它的区别一开始很难理解,但一旦你明白了;你会希望看到它对于客户端路由是多么强大和完美。

与其考虑 url,不如考虑 can.route 的数据。里面有什么can.route.attr()。例如,您的 URL 似乎包含以下数据:

  • page - 某人正在处理的主要区域
  • 子页面 - 页面内的可选辅助区域
  • id - 类型的 id

例如,admin/users可能想要can.route.attr()返回:

{page: "admin", subpage: "users"}

并且,claims/5可能会转化为:

{page: "claims", id: "5"}

当我开始构建应用程序时,我只使用看起来像的 url,#!page=admin&subpage=users并在以后忽略漂亮的路由。我首先围绕状态构建应用程序。

一旦我对can.route.attr()封装我的应用程序状态的数据有了初步的了解,我就会构建一个routing app模块来监听变化can.route并设置正确的控件或组件。你的可能看起来像:

can.route.bind("change", throttle(function(){
  if( can.route.attr("page") == "admin" ) {
    load("AdminController")
  } else if(can.route.attr("page") === "claims" && can.route.attr("id") {
    load("ClaimController")
  } else if ( ... ) { 
    ... 
  } else {
    // by convention, load a controller for whatever page is
    load(can.capitalize(can.route.attr("page")+"Controller")
  }

}) );

最后,在设置完所有这些之后,我将漂亮的路线映射到我的预期can.route.attr()值:

can.route(":page"); // for #!claims, #!admin
can.route("claims/new", {page: "claims", subpage: "new"});
can.route("claims/:id", {page: "claims"});
can.route("admin/:subpage",{page: "admin"});

通过这样做,您可以使您的路由独立于应用程序的其余部分。一切都只是监听 can.route 属性的变化。您的所有路由规则都维护在一个地方。

于 2014-09-10T23:23:17.200 回答