diff --git a/docs/.vuepress/configs/sidebar/zh.ts b/docs/.vuepress/configs/sidebar/zh.ts index 46dc53dd..dcd618c7 100644 --- a/docs/.vuepress/configs/sidebar/zh.ts +++ b/docs/.vuepress/configs/sidebar/zh.ts @@ -15,6 +15,7 @@ export const zh: SidebarConfig = { text: '基础', children: [ '/zh/guide/directory-structure.md', + '/zh/guide/route.md', ] }, { diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index a57e676b..6b789cde 100644 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -1,3 +1,3 @@ .page .page-meta, .page-nav, .theme-default-content:not(.custom) - max-width: 800px \ No newline at end of file + max-width: 1000px \ No newline at end of file diff --git a/docs/zh/guide/README.md b/docs/zh/guide/README.md index fe25fd51..da4cbb7b 100644 --- a/docs/zh/guide/README.md +++ b/docs/zh/guide/README.md @@ -72,4 +72,4 @@ Vue CLI 是基于 Vue.js 进行快速开发的完整系统,提供交互式脚 ### UMI -UMI 是个很好的选择,Fes.js 很多功能是借鉴 UMI 做的。如果 UMI 对 Vue 支持足够够好的话,可能 Fes.js 2.0 版本就不会出现了。喜欢 React 的同学推荐使用 UMI。 +UMI 是个很好的选择,Fes.js 很多功能是借鉴 UMI 做的。UMI 是基于 React 封装的应用级框架,贯彻着函数式编程的思维。而 Vue 有所不同,虽然 Vue 3.0 向函数式迈了一大步,但大家可能依然喜欢编写 `.vue`文件,而非 `.jsx` 文件。两种思维方式会导致部分API设计上有所差异,虽然 UMI 有 `plugin-vue` ,但不太 "vue"。推荐喜欢 React 的同学使用 UMI。 diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md index 5e7f558a..726500c0 100644 --- a/docs/zh/guide/getting-started.md +++ b/docs/zh/guide/getting-started.md @@ -53,10 +53,11 @@ npx @webank/create-fes-app myapp -如果项目目录 `workspace/myapp` 已经存在,则会提示目录已存在,你可以选择 `Overwrite` 删除目录后重新创建项目,也可以选择 `Merge` 使用模板文件覆盖当前目录文件。 +如果项目目录 `workspace/myapp` 已经存在,则会提示目录已存在,你可以选择 `Overwrite` 删除目录后重新创建项目,也可以选择 `Merge` 使用模板文件覆盖当前目录文件。 ![目录已存在提示](/pickTemplateTip.png) -如果项目目录 `workspace/myapp` 不存在,你会被提示选取一个 template。你可以选默认适用于中后台前端应用的 `PC` 类型,也可以选适用于移动端的 `H5` 类型。 +如果项目目录 `workspace/myapp` 不存在,你会被提示选取一个 template。你可以选默认适用于中后台前端应用的 `PC` 类型,也可以选适用于移动端的 `H5` 类型。 + ![选择模板类型](/pickTemplate.png) ##### 步骤3 安装依赖 diff --git a/docs/zh/guide/route.md b/docs/zh/guide/route.md new file mode 100644 index 00000000..940c5b2b --- /dev/null +++ b/docs/zh/guide/route.md @@ -0,0 +1,250 @@ +# 路由 + +像Vue、React这类框架是用组件化搭建页面,路由解决的是路径到组件的匹配问题。Fes.js 基于 [Vue Router](https://next.router.vuejs.org/) 实现了路由,感兴趣的同学可以看看。 + +## 路由配置 + +在配置文件中通过 router 进行配置,格式为路由信息的数组。 +```js +export default { + router: { + routes: [], + mode: 'hash' + } +} +``` + +### routes +添加到路由的初始路由列表。具体使用参考 [Vue Router 文档](https://next.router.vuejs.org/zh/guide/) + + +### mode +创建 Histroy 的类型: +- **h5**,对应 [createWebHistory](https://next.router.vuejs.org/zh/api/#createwebhistory) +- **hash**,对应 [createWebHashHistory](https://next.router.vuejs.org/zh/api/#createWebHashHistory) +- **memory**,对应 [createMemoryHistory](https://next.router.vuejs.org/zh/api/#createWebHashHistory) + +## 约定式路由 +约定式路由也叫文件路由,就是不需要手写配置,文件系统即路由,通过目录和文件及其命名分析出路由配置。 + +### 约定规范 +比如以下文件结构: +``` +pages +├── index.vue # 根路由页面 路径为 / +├── *.vue # 模糊匹配 路径为 * +├── a.vue # 路径 /a +├── b # 文件夹b +│ ├── index.vue # 路径 /b +│ ├── @id.vue # 动态路由 /b/:id +│ ├── c.vue # 路径 /b/c +│ └── layout.vue # /b 路径下所有页面公共的布局组件 +└── layout.vue # 根路由下所有页面共用的布局组件 +``` +编译后会得到以下路由配置: +```js +[ + { + "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": "*", + "component": require('@/pages/*').default, + "name": "FUZZYMATCH", + "meta": {}, + "count": 3 + } + ] + } +] +``` + +### 动态路由 +Fes.js 里约定以 `@` 开头的文件或文件夹映射为动态路由。 +比如: + +- `src/pages/users/@id.vue` 会成为 `/users/:id` +- `src/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 +``` +会生成路由: +```js +[ + { + 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 }, + ] + } +] +``` + +### 模糊匹配 +Fes.js 下约定文件名为 `*` 的路由是模糊匹配路由,可以用此特性实现404路由。 + +比如以下目录结构: + +``` +pages +├── index.vue # 根路由页面 路径为 / +└── *.vue # 模糊匹配 路径为 * +``` +会生成路由: +```js +[ + { + path: '/', component: require('@/pages/index').default, count: 5 + }, + { + path: '*', component: require('@/pages/**').default, count: 3 + } +] +``` +这样,如果访问 `/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 } + } + ] + } + ] +}) +``` +在 Fes.js 里约定在 `.vue` 文件中的 `config` 为 `meta` 配置。如果 'pages/a.vue' 中有如下配置: +```vue + +{ + "name": "store", + "title": "vuex测试" +} + +``` +则编译后的路由配置为: +```js +[ + { + path: '/a', + component: require('@/pages/a').default, + meta: { + "name": "store", + "title": "vuex测试" + } + }, +] +``` + +### 忽略 +需要注意的是,满足以下任意规则的文件不会被注册为路由: +- 不是 .vue 文件 +- components 目录中的文件 + + +### 智能路由 +可以看到,编译后路由都会有count属性,这是我们根据精准匹配优先算法原则设计出路由排名算法,对匹配到的路由打分: +- 路由的路径每个子项得到4分 +- 子项为静态细分(`/list`)再加3分 +- 子项为动态细分(`/:orderId`)再加2分 +- 根段(`/`)再1分 +- 通配符(`*`)匹配到的减去1分 + +当我们跳转路由时,如果URL匹配到多个路由,则选择分数最高的路由。 + +## 路由跳转 +页面跳转 API 由 `router` 实例提供,查看 [Vue Rouer 文档](https://next.router.vuejs.org/zh/api/#router-%E6%96%B9%E6%B3%95)了解更多。 + +```js +import { useRouter } from '@webank/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'); + } +} + +``` \ No newline at end of file diff --git a/docs/zh/reference/api/README.md b/docs/zh/reference/api/README.md index a4aa5408..c4e6000f 100644 --- a/docs/zh/reference/api/README.md +++ b/docs/zh/reference/api/README.md @@ -119,7 +119,7 @@ export default { ::: tip 在开发插件时可能用上,平时一般用不上 ::: -创建哈希历史记录。对于没有 `host`(例如file://)或者需要部署在非根目录时非常有用 。请注意,如果SEO对您很重要,您应该使用`createWebHistory`。 +创建一个 hash 历史记录。对于没有主机的 web 应用程序 (例如 file://),或当配置服务器不能处理任意URL时这非常有用。注意:如果 SEO 对你很重要,你应该使用 `createWebHistory`。 ### createWebHistory ::: tip @@ -131,7 +131,7 @@ export default { ::: tip 在开发插件时可能用上,平时一般用不上 ::: -创建基于内存的历史。此历史的主要目的是处理 SSR。它开始于一个特殊的混沌 location 。如果用户不在浏览器上下文中,则由他们通过调用`router.push()`或`router.replace()`变更 location。 +创建一个基于内存的历史记录。这个历史记录的主要目的是处理 SSR。它在一个特殊的位置开始,这个位置无处不在。如果用户不在浏览器上下文中,它们可以通过调用 router.push() 或 router.replace() 将该位置替换为启动位置。 ### createRouter 创建一个路由器实例,该实例可用于 Vue 应用程序。查看[路由器选项](https://next.router.vuejs.org/api/#routeroptions),了解可以传递的所有属性的列表。