ThinkJS 提供了一套灵活的路由机制,除了默认的解析外,还可以支持多种形式的自定义路由,让 URL 更加简单友好。

    当用户访问服务时,服务端首先拿到的是一个完整的 URL,如:访问本页面,得到的 URL 为 。

    将 URL 进行解析得到的 pathname 为 /zh-cn/doc/2.0/route.html

    pathname 过滤

    有时候为了搜索引擎优化或者一些其他的原因, URL 上会多加一些东西。比如:当前页面是一个动态页面,但 URL 最后加了 .html,这样对搜索引擎更加友好。但这些在后续的路由解析中是无用的,需要去除。

    ThinkJS 里提供了下面的配置可以去除 pathname 的前缀和后缀内容:

    上面配置可以在 src/common/config/config.js 中进行修改。

    pathname 过滤时会自动去除左右的 /,该逻辑不受上面的配置影响。对 pathname 进行过滤后,拿到干净的 pathname 为 zh-cn/doc/2.0/route

    :如果访问的 URL 是 ,那么最后拿到干净的 pathname 则为空字符串。

    子域名部署请见Middleware -> 子域名部署

    路由识别

    路由解析

    路由识别默认根据 模块/控制器/操作/参数1/参数1值/参数2/参数2值 来识别过滤后的 pathname,如:pathname 为 admin/group/detail,那么识别后的结果为:

    • module 为 admin
    • controller 为 group
    • action 为 detail,对应的方法名为 detailAction
      如果项目里并没有 admin 这个模块或者这个模块被禁用了,那么识别后的结果为:

    • controller 为 admin
    • action 为 group,对应的方法名为 groupAction
    • 参数为 {detail: ''}
      如果有多级控制器,那么会进行多级控制器的识别,然后才是 action 的识别。

    大小写转化

    路由识别后,modulecontrollerAction 值都会自动转为小写。如果 Action 值里有 _,会作一些转化,如:假设识别后的 Controller 值为 index,Action 值为 user_add,那么对应的 Action 方法名为 userAddAction,但模版名还是 index_user_add.html

    当解析 pathname 没有对应的值时,此时便使用对应的默认值。其中 module 默认值为 home,controller 默认值为 index,action 默认值为 index

    这些值可以通过下面的配置进行修改,配置文件 src/common/config/config.js

    1. export default {
    2. default_module: 'home',
    3. default_controller: 'index',
    4. default_action: 'index',
    5. }

    自定义路由

    默认的路由虽然看起来清晰明了,解析起来也很简单,但看起来不够简洁。

    有时候需要更加简洁的路由,这时候就需要使用自定义路由解析了。如:文章的详细页面,默认路由可能是:article/detail/id/10,但我们想要的 URL 是 article/10 这种更简洁的方式。

    开启配置

    开启自定义路由,需要在 开启如下的配置:

    1. export default {
    2. route_on: true
    3. }
    路由规则

    开启自定义路由后,就可以通过路由规则来定义具体的路由了,路由配置文件为: src/common/config/route.js,格式如下:

    1. export default [
    2. ["规则1", "需要识别成的pathname"],
    3. ["规则2", {
    4. get: "get请求下需要识别成的pathname",
    5. post: "post请求下需要识别成的pathname"
    6. }]
    7. ];

    :自定义路由每一条规则都是一个数组。(至于为什么不用对象,是因为正则路由下,正则不能作为对象的 key 直接使用)

    识别方式

    自定义路由的匹配规则为:从前向后逐一匹配,如果命中到了该项规则,则不在向后匹配。


    ThinkJS 支持 3 种类型的自定义路由,即:正则路由,规则路由和静态路由。

    正则路由

    正则路由是采用正则表示式来定义路由的一种方式,依靠强大的正则表达式,能够定义非常灵活的路由规则。

    1. export default class extends think.controller.base {
    2. detailAction(){
    3. }
    4. }

    如果正则里含有多个子分组,那么可以通过 :1:2:3 来获取对应的值。

    1. export default [
    2. [/^article\/(\d+)$/, {
    3. get: "home/article/detail?id=:1",
    4. delete: "home/article/delete?id=:1",
    5. post: "home/article/save?id=:1"
    6. }]
    7. ];

    规则路由

    规则路由是一种字符串匹配方式,但支持含有一些动态的值。如:

    1. ['group/:year/:month', "home/group/list"]
    2. ]

    假如访问的 URL 为 http://www.example.com/group/2015/10,那么会命中该项规则,得到的 pathname 为 home/group/list,同时会添加 2 个参数 yearmonth,这2个参数可以在控制器里通过 this.get 方法来获取。

    静态路由

    静态路由是一种纯字符串的完全匹配方式,写法和识别都很简单,功能也相对要弱很多。

    1. export default [
    2. ["list", "home/article/list"]
    3. ]

    假如访问的 URL 为 http://www.example.com/list,那么替换后的 pathname 为 home/article/list

    优化路由性能

    上面已经说到,自定义路由是个数组,数组每一项是个具体的路由规则,匹配时是从前向后逐一进行匹配。如果这个路由表比较大的话,可能会有性能问题。

    为了避免有性能问题,ThinkJS 提供了一种更加高效的自定义路由方式,按模块来配置路由。使用这种方式,路由配置格式跟上面稍微有所不同。

    common/config/route.js

    使用这种方式后,通用模块里的路由配置不再配置具体的路由规则,而是配置哪些规则命中到哪个模块。如:

    1. export default {
    2. admin: {
    3. reg: /^admin/ //命中 admin 模块的正则
    4. },
    5. home: { //默认走 home 模块
    6. }
    7. }
    admin/config/route.js

    admin 模块配置 admin 下的具体路由规则。

    1. export default [
    2. [/^admin\/(?!api).*$/, 'admin/index'],
    3. [/^admin\/api\/(\w+?)(?:\/([\d,]*))?$/, 'admin/:1?id=:2&resource=:1'],
    4. ];

    假设访问的 URL 为 http://www.example.com/admin/api,那么解析后的 pathname 为 admin/api,匹配 common 里的规则时会命中 admin 模块,然后再对 admin 模块下的路由规则进行逐一匹配。通过这种方式后就可以大大减少路由规则匹配的数量,提供匹配效率。

    首页默认执行的是 index controller 里的 indexAction。有些项目里希望对首页路由自定义,但配置 ['', 'index/list'] 并不管用。