文档更新

master
toesbieya 5 years ago
parent 21f31cfed1
commit 8d4ec74514
  1. 12
      docs/frontend/README.md
  2. 118
      docs/frontend/layout.md
  3. 117
      docs/frontend/router.md
  4. 9
      vue/full/src/router/index.js

@ -2,6 +2,8 @@
这是在[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) 的基础上改造而来的。
布局使用的是[el-admin-layout](https://github.com/toesbieya/el-admin-layout)
分为需要配合后端使用的full版(vue/full)和精简版(vue/template),以下说明均以full版为准。
## 功能
@ -15,14 +17,6 @@
- 动态路由、动态菜单
- 布局
- 异步路由组件loading骨架屏
- 多种导航模式
- 仿ant design响应式的顶部菜单
- 无限级递归菜单
- 多页签(支持详情页缓存)
- 支持移动端
- Excel导出,支持多级表头、合并行
- element-ui增强
@ -46,7 +40,7 @@
│ ├── directive # 全局指令
│ ├── filter # 自定义过滤器集合
│ ├── globalMethod # 全局方法,已挂载到Vue原型上,使用this.$xx调用
│ ├── layout # 布局文件夹,包含了导航栏、侧边栏、多页签、全局页脚
│ ├── layout # 布局
│ ├── mixin # 公用混入
│ ├── plugin # 一些插件,均使用import()来动态引入
│ ├── router

@ -2,120 +2,6 @@
<img :src="$withBase('/布局.png')">
布局也是一个组件,比较重型而已,文件目录:`@/layout/index.vue`。
此布局是在vue-element-admin的基础上改造而来,并且模仿and design pro实现了三种导航模式。
实际上这个布局算是二级路由,一级路由是 `App.vue`,这就是为什么经常会看到路由会这么写的原因:
```json
{
"path": "/",
"component": Layout,
"children": [
{
"path": "index",
"name": "index",
"component": Page
}
]
}
```
`Layout`(指`@/layout/index.vue`) 填充到 `App.vue` 里的 `<router-view>`
而真正的路由页面 `Page` 则填充到 `Layout` 里的 `<router-view>`
当然,如果 `Layout` 中**没有写** `<router-view>`,那么只会显示布局组件。
项目中没有用到 `Layout` 的页面只有 `@/router/define.js` 里的 `login`、`403`、`404`、`500`。
此外,在写 `Layout` 这个重型组件时,已经尽可能地进行独立化(拥有作为独立组件的可能性)。
目前 `Layout` 的数据控制基本由 `Vue.observable` 实现(文件都在 `@/layout/store` 下),
仅有*未读消息数*、*用户信息*需要使用 `vuex`
## 侧边栏
文件目录:`@/layout/component/Aside/index.vue`。
扩展了抽屉模式、自动隐藏这两个功能。
侧边栏**不会**在以下情形渲染:
- PC端下选择了顶部导航模式
- 没有需要显示的菜单(仅不渲染dom)
### 侧边栏LOGO
文件目录:`@/layout/component/Aside/Logo.vue`。
想更改logo地址的请修改 `@/config/index.js` 中的 `sidebarLogoUrl`,或者自己重写(需要注意侧边栏的折叠情况)
### 侧边栏菜单
侧边栏菜单借助了 `@/component/menu/NavMenu/item.vue` 来渲染菜单项,具体配置请查看[路由配置](./router.html)。
侧边栏菜单扩展了以下功能:
- 点击已激活的菜单可刷新路由
- 折叠时可显示父级菜单
- 菜单激活时自动滚动到可视区域
## 头部导航栏
文件目录:`@/layout/component/Header/component/Navbar/index.vue`。
### 汉堡包
文件目录:`@/layout/component/Header/component/Navbar/Hamburger.vue`。
PC端的行为是切换侧边栏的折叠状态,移动端是切换侧边栏在抽屉模式下的显示状态。
当侧边栏无需渲染时,汉堡包同样不会渲染。
### 导航菜单
文件目录:`@/layout/component/Header/component/Navbar/HeadMenu.vue`。
头部导航菜单基本可以视为垂直版的侧边栏菜单,也具有*点击已激活的菜单可刷新路由*的功能,此外还扩展了以下功能:
- 仿ant design的响应式
头部导航菜单**不会**在以下情形渲染:
- 是移动端
- PC端下选择了侧边栏导航模式
### 设置面板
<img :src="$withBase('/布局-设置面板.png')">
文件目录:`@/layout/component/Header/component/Navbar/SettingDrawer.vue`。
设置面板的数据与`Layout`的数据是相互独立的,这么做是为了`Layout`的独立性。
在设置面板中修改数据后,会将配置写入localStorage。
在面板mounted时,会将localStorage中的配置数据同步到`Layout`的store中
## 头部多页签
文件目录:`@/layout/component/Header/component/Tagsview/index.vue`。
在原版的基础上扩展了以下功能:
- 平滑滚动
- 快捷键响应:`ctrl + → 下一个页签`、`ctrl + ← 上一个页签`
::: warning 注意
多页签在 启用 / 停用 之间切换时,之前缓存的页签实例会清空,也就是说再次打开时会是新的页面
:::
## 路由页面
文件目录:`@/layout/component/Page/index.vue`。
### 页头
文件目录:`@/layout/component/Page/PageHeader.vue`。
将原先在头部导航栏的面包屑挪到了这里(参考[dcat-admin](https://github.com/jqhph/dcat-admin))。
这里说明一下面包屑的实现,是直接用$route.matched做的,没有考虑其他特殊情况。
不想显示页头的可以将路由配置项的`meta.pageHeader`设为`false`。
### 页脚
文件目录:`@/layout/component/Page/component/PageFooter.vue`。
只是一个静态dom,想咋改就咋改。
目前页脚全局显示,没有提供配置来隐藏,不想显示的直接删除即可。
该布局用的是[el-admin-layout](https://github.com/toesbieya/el-admin-layout) ,[文档](https://doc.toesbieya.cn/el-admin-layout/)
项目中没有用到该布局的页面只有 `@/router/define.js` 里的 `login`、`403`、`404`、`500`。

@ -67,55 +67,19 @@ const routes = [
此外,所有根节点(经过降级缩减)的`redirect`属性都将设为其第一个子节点的`fullPath`,`redirect`有值的不作处理。
路由配置会经过一些变换以转换成el-admin-layout需要的菜单,所以项目中的路由meta的数据结构为el-admin-layout中[路由meta](https://doc.toesbieya.cn/el-admin-layout/api/#%E8%B7%AF%E7%94%B1meta%E9%85%8D%E7%BD%AE) 和[菜单meta](https://doc.toesbieya.cn/el-admin-layout/api/#%E8%8F%9C%E5%8D%95%E9%85%8D%E7%BD%AE)的统合
### Route.meta Attributes:
因为一些需要,项目中的路由meta相比于上述会多一些,具体如下表:
### Route.meta Extra Attributes:
| 参数 | 说明 | 类型 | 默认 |
| :------------: | :--------------------------------------------------: | :--------: | :---: |
| title | 路由在侧边栏、面包屑、页签的名称 | `string` | - |
| dynamicTitle | 路由在面包屑、页签中的动态名称,参数为(to,from) | `function` | - |
| hidden | 是否在菜单中隐藏 | `boolean` | - |
| alwaysShow | 是否总是把只有一个子级的菜单以嵌套模式展示 | `boolean` | - |
| sort | 侧边栏的排序值,值越小越靠前 | `number` | 10000 |
| icon | 图标名,`<v-icon>`的icon属性 | `string` | - |
| affix | 是否在多页签中固定显示 | `boolean` | - |
| noCache | true时不缓存页面 | `boolean` | - |
| activeMenu | 当前激活菜单的index,因为激活菜单可能并非当前路由 | `string` | - |
| noAuth | true时路由不需要鉴权 | `boolean` | - |
| iframe | 需要打开的iframe的地址 | `string` | - |
| usePathKey | 是否使用$route.path作为组件缓存的key | `boolean` | - |
| useFullPathKey | 是否使用$route.fullPath作为组件缓存的key | `boolean` | - |
| commonModule | 共用组件的唯一标识,用于判断路由是否复用组件 | `any` | - |
::: tip 注意
路由meta上的noAuth、noCache会被子路由继承,优先使用子路由的值
:::
## 页面缓存
先总结一下路由页面被缓存的条件:
- 启用了多页签(`@/layout/store/tagsView.js`中的`enabled`为`true`)
- `(route.name || route.meta.usePathKey || route.meta.useFullPathKey) && !route.meta.noCache && !route.meta.iframe`
通常情况路由想做缓存都是通过 `<keep-alive>`,但是如果是像 `/edit/1`、`/edit/2` 这样的共用路由页面的详情页的话,
`<keep-alive>` 就满足不了需求,因为它是通过组件的 `name` 来区分组件的。
所以项目中仿照 `<keep-alive>` 写了 `<keep-router-view-alive>`,可以根据当前路由的路径来区分组件。
除此之外还有个问题,在共用了同一个组件的路由之间跳转的话,组件会被复用,假如有以下路由:
```js
const component={template:`<input v-model="data">`, data: ()=> ({data:1})}
const routes = [
{ path: '/foo', component },
{ path: '/bar', component }
]
```
先访问 `/foo`,然后将输入框的值改为100,再访问 `/bar` ,会发现输入框的值还是100。
所以在 `router.beforeEach` 中做了判断,如果跳转前后的路由的 `meta.commonModule` 相同的话,
那么借助 `/redirect` 跳转一次,从而避免组件复用的问题
::: warning 注意
如果使用`name`作为组件缓存的标识,那么缓存的页面的`name`必须和路由的`name`一致
路由meta上的`noCache`、`noAuth`会被子路由继承,优先使用子路由的值
:::
## 路由免登陆
@ -134,10 +98,7 @@ const noLoginList = ['/login', '/register', '/403', '/404', '/500']
预设的路由守卫如下:
- nprogress进度条守卫
- 防止路由复用组件的守卫
- 修改页面标题信息的守卫
- 登陆和权限守卫
- 控制iframe显隐的守卫
::: warning 注意
路由守卫是有先后顺序的,请查看`@/router/guardian/index.js`
@ -152,7 +113,7 @@ const noLoginList = ['/login', '/register', '/403', '/404', '/500']
原理很简单,在 `index.html` 里有这么一段:
```html
<div id="app">
<div id="loader-wrapper">
<div>
<img>
<p>资源加载中......</p>
</div>
@ -183,69 +144,3 @@ component: lazyLoadView(import(...))
[这是vue-router的官方文档](https://github.com/vuejs/vue-router/pull/2140/files) ,项目中具体的使用方式可以查看 `@/router/util #generateRoutes`方法。
关于 `AsyncHandler` 的更多选项,可以查看[vue官方文档](https://cn.vuejs.org/v2/guide/component-dynamic-async.html#%E5%A4%84%E7%90%86%E5%8A%A0%E8%BD%BD%E7%8A%B6%E6%80%81)
## 过渡动画
正常 `<router-view>` 使用过渡动画的方法应该是这样的:
```html
<transition>
<keep-alive>
<router-view>
</keep-alive>
</transition>
```
但是由于项目中使用了自定义的 `<keep-router-view-alive>`,所以就变成这样的:
```html
<keep-router-view-alive>
<transition>
<router-view>
</transition>
</keep-router-view-alive>
```
具体原因是 `<transition>` 中的代码硬编码了 `<keep-alive>`,导致如果按照往常写法的话,过渡动画不会生效。
项目中是根据页签的前后位置来决定路由动画的,比如从前面的页签跳转到后面的,那么动画是从左滑出,反之是从右滑出,源码位于`@/layout/mixin/decideRouterTransition.js`。
::: warning 注意
只有在启用了多页签的时候才会有上面的效果,否则默认是 `@/config/index.js` 中的 `route.animate.default` 动画。
:::
## iframe
只需要按如下配置即可打开一个iframe:
```json
{
"path":"/baidu",
"meta":{
"iframe":"https://www.baidu.com"
}
}
```
当向上面的路由跳转时,会隐藏路由页面,展示 `<iframe>` 标签,反之则隐藏。
另外,相同地址的iframe不会重复打开,想要刷新需使用 `/redirect` 跳转。
iframe页面的缓存与普通页面相同,都是使用 `meta.noCache` 控制。
## 外链
也可以在路由中配置一个外链,只要在 `path` 中填写了以 `'http'` 开头的路径,当你点击该路由菜单时就会新开这个页面。
外链**只**存在与菜单中,**不会**被 `vue-router` 识别。
例如:
```json
{
"path": "https://www.baidu.com",
"meta": {
"title": "百度"
}
}
```
::: tip 注意
由于在`<el-menu>`中,菜单(`<el-menu-item>`)只要被点击就会高亮,所以如果不希望外链菜单被高亮,
那么需要在点击后通过调用`<el-menu>`的`updateActiveIndex`方法来重新设置高亮菜单。
:::

@ -2,14 +2,7 @@
* 路由配置说明
*
* 不需要鉴权的路由meta.noAuth
* 左侧菜单显示name && !meta.hidden && meta.title
* 左侧菜单排序能在左侧菜单中显示 && meta.sort升序排列
* 左侧菜单不折叠只有一个children的路由meta.alwaysShow
* 页头显示meta.pageHeader !== false && (meta.title || meta.dynamicTitle)
* tab栏显示meta.title || meta.dynamicTitle
* tab栏固定显示meta.title && meta.affix
* 页面不缓存!name && !meta.usePathKey && !meta.useFullPathKey || meta.noCache
* 打开iframemeta.iframe不会重复打开相同src的iframe
* 更多请查看[el-admin-layout](https://doc.toesbieya.cn/el-admin-layout/api/)
*/
import Vue from 'vue'

Loading…
Cancel
Save