路由
像 Vue 、React 这类框架是用组件化搭建页面,路由解决的是路径到组件的匹配问题。Fes.js 基于 Vue Router 实现的路由,想了解更多的同学可以看看官方文档在新窗口打开。
路由配置
在配置文件 .fes.js中通过 router 进行配置。
export default {
    router: {
        routes: [],
        mode: 'hash'
    }
}
2
3
4
5
6
routes
routes 是配置添加到路由的初始路由列表,格式为路由信息的数组。具体使用参考 Vue Router 文档在新窗口打开 中关于路由配置、路由匹配相关内容。
mode
创建历史记录的类型:
- history,对应 createWebHistory在新窗口打开
 - hash,对应 createWebHashHistory在新窗口打开
 - memory,对应 createMemoryHistory在新窗口打开
 
默认是hash模式。
约定式路由
约定式路由也叫文件路由,就是不需要手写配置,文件系统即路由,通过目录和文件及其命名分析出路由配置。
约定规范
比如以下文件结构:
pages
├── index.vue         # 根路由页面 路径为 /
├── [...slug].vue     # 模糊匹配 路径为 /:slug(.*)
├── a.vue             # 路径 /a
├── b                 # 文件夹b
│   ├── index.vue     # 路径 /b
│   ├── @id.vue       # 动态路由 /b/:id
│   ├── c.vue         # 路径 /b/c
│   └── layout.vue    # /b 路径下所有页面公共的布局组件
└── layout.vue        # 根路由下所有页面共用的布局组件
2
3
4
5
6
7
8
9
10
编译后会得到以下路由配置:
[
    {
        "path": "/",
        "component": require('@/pages/layout').default,
        "count": 5,
        "children": [
            {
                "path": "/a",
                "component": require('@/pages/a').default,
                "name": "a",
                "meta": {},
                "count": 7
            },
            {
                "path": "/b",
                "component": require('@/pages/b/layout').default,
                "count": 7,
                "children": [
                    {
                        "path": "/b/c",
                        "component": require('@/pages/b/c').default,
                        "name": "b_c",
                        "meta": {},
                        "count": 14
                    },
                    {
                        "path": "/b/:id",
                        "component": require('@/pages/b/@id').default,
                        "name": "b__id",
                        "meta": {},
                        "count": 13
                    },
                    {
                        "path": "/b",
                        "component": require('@/pages/b/index').default,
                        "name": "b_index",
                        "meta": {},
                        "count": 7
                    }
                ]
            },
            {
                "path": "/",
                "component": require('@/pages/index').default,
                "name": "index",
                "meta": {},
                "count": 5
            },
            {
                "path": "/:pathMatch(.*)",
                "component": require('@/pages/*').default,
                "name": "FUZZYMATCH",
                "meta": {},
                "count": 3
            }
        ]
    }
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
需要注意的是,满足以下任意规则的文件不会被注册为路由:
- 不是 
.vue .jsx文件 components目录中的文件
动态路由
Fes.js 里约定以 @ 开头的文件或文件夹映射为动态路由。 比如:
src/pages/users/@id.vue会成为/users/:idsrc/pages/users/@id/settings.vue会成为/users/:id/settings
嵌套路由
Fes.js 里约定目录下有 layout.vue 时会生成嵌套路由,以 layout.vue 为该目录的公共父组件,layout.vue 中必须实现 RouterView
比如以下目录结构:
pages
└── users
    ├── layout.vue
    ├── index.vue
    └── list.vue
2
3
4
5
会生成路由:
[
    { 
        path: '/users', component: require('@/pages/users/layout').default,
        children: [
            { path: '/users', component: require('@/pages/users/index').default },
            { path: '/users/list', component: require('@/pages/users/list').default },
        ]
    }
]
2
3
4
5
6
7
8
9
模糊匹配
Fes.js 下约定文件名为 * 的路由是模糊匹配路由,可以用此特性实现 404 路由在新窗口打开。
比如以下目录结构:
pages
├── index.vue         # 根路由页面 路径为 /
└── *.vue             # 模糊匹配 路径为 *
2
3
会生成路由:
[
    { 
        path: '/', component: require('@/pages/index').default, count: 5
    },
    {
        path: '/:pathMatch(.*)', component: require('@/pages/**').default, count: 3
    }
]
2
3
4
5
6
7
8
这样,如果访问 /foo,/ 不能匹配,会 fallback 到 * 路由,通过 src/pages/*.vue 进行渲染。
扩展路由元信息
我们在定义路由时可以配置meta字段,用来记录一些跟路由相关的信息:
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
接下来我们来配置 meta:
<config>
{
    "name": "store",
    "title": "vuex测试"
}
</config>
2
3
4
5
6
import { defineRouteMeta, useRoute } from '@fesjs/fes';
defineRouteMeta({
    name: "store",
    title: "vuex测试"
})
2
3
4
5
import { defineRouteMeta, useRoute } from '@fesjs/fes';
defineRouteMeta({
    name: "store",
    title: "vuex测试"
})
2
3
4
5
则编译后的路由配置为:
[
    { 
        path: '/a', 
        component: require('@/pages/a').default, 
        meta: {
            "name": "store",
            "title": "vuex测试"
        }
    },
]
2
3
4
5
6
7
8
9
10
智能路由
可以看到,编译后路由都会有 count 属性,这是我们根据精准匹配优先算法原则设计出路由排名算法,对匹配到的路由打分:
- 路由的路径每个子项得到4分
 - 子项为静态细分(
/list)再加3分 - 子项为动态细分(
/:orderId)再加2分 - 根段(
/)再1分 - 通配符(
*)匹配到的减去1分 
当我们跳转路由时,如果 URL 匹配到多个路由,则选择分数最高的路由。
路由跳转
想学习更多,可以查看 Vue Router 官方文档在新窗口打开。
声明式
<template>
    <router-link to="/home">Home</router-link>
</template>
2
3
命令式
页面跳转 API 由 router 实例提供,查看 Vue Rouer 文档在新窗口打开了解更多。
import { useRouter } from '@fesjs/fes';
export default {
    setup(){
        const router = useRouter();
        // 这三种形式是等价的
        router.push('/users/posva#bio')
        router.push({ path: '/users/posva', hash: '#bio' })
        router.push({ name: 'users', params: { username: 'posva' }, hash: '#bio' })
        // 只改变 hash
        router.push({ hash: '#bio' })
        // 只改变 query
        router.push({ query: { page: '2' } })
        // 只改变 param
        router.push({ params: { username: 'jolyne' } })
        // 跳转到上一个路由
        router.goBack();
        // 跳转到前一个历史记录
        router.go(1);
        // 替换历史堆栈中的记录
        router.replace('/new');
    }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27