Can.js中的路由约定

时间:2014-09-10 22:22:14

标签: canjs canjs-routing

所以我想在我的超酷can.js应用程序中制作一些路线。瞄准这样的事情......

#!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路由匹配,然后重新加载Claim Controller,显示从服务器/缓存中提取的新版索赔,失去了我的变化。

为了尝试定义问题,我需要路由器来识别路由何时发生变化,路由属于哪个控制器,以及如果控制器已经加载,则忽略它。但这很难!

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都是相同的。

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

1 个答案:

答案 0 :(得分:5)

以下是我在复杂的CanJS应用程序中设置路由的方法。您可以看到此here的示例。

首先,不要使用can.Control路由。它是一种反模式,将在3.0中删除this issue中的想法。

而是设置一个routing app模块,该模块按惯例导入和设置模块,类似于使用thishere

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

不要考虑网址,而应考虑can.route的数据。 can.route.attr()中有什么。例如,您的网址似乎包含以下数据:

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

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

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

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

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

当我开始构建应用程序时,我只使用看起来像#!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属性的变化。您的所有路由规则都保存在一个位置。