diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..929eb65 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,22 @@ +.DS_Store +node_modules +/dist +/test + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 0000000..9864f8b --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,69 @@ +module.exports = { + title: 'jxc-admin', + + description: "jxc-admin后台管理系统文档", + + host: 'localhost', + + // 输出目录 + dest: 'dist', + + // 主题配置 + themeConfig: { + smoothScroll: true, + + lastUpdated: '上次更新:', + + nav: [ + {text: '在线预览', link: 'https://toesbieya.cn'}, + {text: 'GitHub', link: 'https://github.com/toesbieya/jxc-admin'} + ], + + sidebar: [ + 'installation', + { + title: '前端', + collapsable: false, + children: [ + '/frontend/', + '/frontend/layout', + '/frontend/router', + '/frontend/permission', + '/frontend/new', + '/frontend/deploy', + { + title: '组件', + collapsable: false, + children: [ + '/frontend/components/abstract-table', + '/frontend/components/region-selector', + '/frontend/components/search-form', + '/frontend/components/upload-file', + ] + }, + { + title: '全局方法', + collapsable: false, + children: [ + '/frontend/global-methods/bottom-tip', + '/frontend/global-methods/guide', + '/frontend/global-methods/image-viewer', + '/frontend/global-methods/puzzle-verify', + '/frontend/global-methods/signature', + ] + }, + '/frontend/utils', + '/frontend/plugins' + ] + }, + ] + }, + + plugins: { + '@vuepress/pwa': { + serviceWorker: true, + updatePopup: true + }, + '@vuepress/back-to-top': true + } +} diff --git a/docs/.vuepress/public/abstract-table.png b/docs/.vuepress/public/abstract-table.png new file mode 100644 index 0000000..eb6ed2b Binary files /dev/null and b/docs/.vuepress/public/abstract-table.png differ diff --git a/docs/.vuepress/public/puzzle-verify.png b/docs/.vuepress/public/puzzle-verify.png new file mode 100644 index 0000000..52c0ac1 Binary files /dev/null and b/docs/.vuepress/public/puzzle-verify.png differ diff --git a/docs/.vuepress/public/region-selector_tab.png b/docs/.vuepress/public/region-selector_tab.png new file mode 100644 index 0000000..772af8b Binary files /dev/null and b/docs/.vuepress/public/region-selector_tab.png differ diff --git a/docs/.vuepress/public/search-form_1.png b/docs/.vuepress/public/search-form_1.png new file mode 100644 index 0000000..ddf656c Binary files /dev/null and b/docs/.vuepress/public/search-form_1.png differ diff --git a/docs/.vuepress/public/search-form_2.png b/docs/.vuepress/public/search-form_2.png new file mode 100644 index 0000000..2d198e6 Binary files /dev/null and b/docs/.vuepress/public/search-form_2.png differ diff --git a/docs/.vuepress/public/upload-file.png b/docs/.vuepress/public/upload-file.png new file mode 100644 index 0000000..fae8447 Binary files /dev/null and b/docs/.vuepress/public/upload-file.png differ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..4e4e7f4 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,9 @@ +--- +home: true +heroImage: https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png +heroText: jxc-admin +tagline: 前后端分离的简易进销存后台管理系统。 +actionText: 快速上手 → +actionLink: ./installation/ +footer: MIT Licensed | Copyright © 2020-present toesbieya +--- diff --git a/docs/frontend/README.md b/docs/frontend/README.md new file mode 100644 index 0000000..4189b7b --- /dev/null +++ b/docs/frontend/README.md @@ -0,0 +1,69 @@ +# 介绍 + +## 功能 + +``` +- 首屏加载动画 + +- 登录 \ 注册 + - 集成多种canvas背景动画 + - 仿极验滑动验证 + +- 布局功能 + - 异步路由组件loading骨架屏 + - 动态侧边栏(支持多级路由嵌套) + - 动态面包屑 + - 多页签(支持详情页缓存) + - 支持移动端 + - 导航栏、侧边栏可隐藏 + - 侧边栏折叠时可显示上级 + +- Excel导出,支持多级表头、合并行 + +- 错误页面 + - 403 + - 404 + +- 组件 + - 用户导航 + - 行政区划选择器,支持树形和选项卡型 + - 封装的上传组件,整合七牛云,支持多种格式的文件预览 + - 封装了antd风格的dialog,可拖拽、超出可滚动 + - 手写签名 + +- element-ui增强 + - message支持分组、进度条功能 + - select重写,分别使用了popperjs的v1和v2版本 +``` + +## 目录结构 +``` +├── element-ui-personal # element-ui增强 +├── mock # 项目mock,需打开devServer.before的注释 +├── public # 静态资源文件夹 +├── src +│ ├── api # 数据请求集合 +│ ├── assets +│ │ │── icons # 项目所有svg icons +│ │ └── styles # 样式集合 +│ ├── bizComponents # 公用业务组件 +│ ├── components # 公用组件 +│ ├── config +│ │ │── index.js # 基础配置项 +│ │ └── request.js # axios封装 +│ ├── directive # 自定义指令集合 +│ ├── filters # 自定义过滤器集合 +│ ├── layout # 布局文件夹,包含了导航栏、侧边栏、多页签、全局页脚、页面 +│ ├── mixins # 公用混入 +│ ├── plugin # 一些插件,均使用import()来动态引入 +│ ├── router +│ │ │── authority # 需要鉴权的路由集合 +│ │ │── constant # 不需要鉴权的路由集合 +│ │ │── index.js +│ │ └── util.js +│ ├── store # vuex配置 +│ ├── utils # 工具类 +│ ├── views # 路由页面集合 +│ ├── App.vue +│ └── main.js +``` diff --git a/docs/frontend/components/abstract-table.md b/docs/frontend/components/abstract-table.md new file mode 100644 index 0000000..b8dbb0f --- /dev/null +++ b/docs/frontend/components/abstract-table.md @@ -0,0 +1,26 @@ +# Abstract Table + + + +给``设置了一些默认属性,设置了`empty`插槽。 +```html + + {children} + + +``` + +### 引入: + +`@/components/AbstractTable`。 + +### 使用: + +照着官方文档,当成 `` 用就行。 + diff --git a/docs/frontend/components/region-selector.md b/docs/frontend/components/region-selector.md new file mode 100644 index 0000000..d00bf7f --- /dev/null +++ b/docs/frontend/components/region-selector.md @@ -0,0 +1,46 @@ +# 行政区划选择器 + +目前分 `树型` 和 `选项卡型` 两种,由于 `树型` 不完善,所以这里只介绍 `选项卡型`,有兴趣的可以查看源码`@/components/RegionSelector/Tree`。 + + + +由于行政区划数据在本项目中是公共数据,所以使用了`vuex`来存放,如果不想用`vuex`但又想拿到别的项目里用,可以自己改造一下。 + +### 引入: + +`@/components/RegionSelector` + +### 使用: +```html + +``` + +行政区划的数据模型可以查看`public/static/json/region-pcas.json`,这是精确到街道的数据,[由此获取](https://github.com/modood/Administrative-divisions-of-China)。 + +### RegionSelector Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| :-----------------: | :-------------------------------------: | :--------------: | :-----: | +| type | 选择器类型,`tab / tree` | `string` | `'tab'` | +| value / v-model | 绑定值 | `string / array` | - | +| readonly | 是否只读,等同于`el-select`的`disabled` | `boolean` | - | +| size | 大小,等同于`el-select`的`size` | `string` | - | +| getChildrenOnSelect | 在确认选择时是否连同子级一起获取 | `boolean` | - | +| limit | 是否需要剪枝 | `boolean` | - | +| limitApi | 获取剪枝数据的api | `function` | - | +| separation | 分隔号 | `string` | `','` | + +### RegionSelector Events: + +| 事件名称 | 说明 | 回调参数 | +| :------: | :------------------------: | :--------------: | +| clear | 等同于`el-select`的`clear` | - | +| select | 确定选择时触发 | `(node,idArray)` | + + +::: tip +`value` 为 `string` 时支持被 `separation` 所连接的汉字或者数字,比如可以是 `北京市,东城区` ,也可以是 `北京市,110101`。 +为 `array` 时,数组里的每一项除了支持上面的形式外,还支持 `{id:'11',...}、{name:'北京市',...}` 这两种。 + +使用 `v-model` 时,不管初始传入的数据是什么样的,最终都会返回 `北京市,东城区` 这样的字符串。 +::: diff --git a/docs/frontend/components/search-form.md b/docs/frontend/components/search-form.md new file mode 100644 index 0000000..42063f0 --- /dev/null +++ b/docs/frontend/components/search-form.md @@ -0,0 +1,59 @@ +# Search Form + +一个自适应的表单容器,根据父元素的内宽来确定一行渲染多少个表单控件,同时确定是否需要折叠。 + + + + +### 引入: + +`@/components/SearchForm`,`@/components/SearchFormItem` + +### 使用: +```html + + + + + + + + + + + + + + + + + + + + + + + +``` + +### SearchForm Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| :-----------------: | :----------------------------------: | :------: | :-------: | +| label-width | 等同于`el-form`的`label-width` | `string` | `'120px'` | +| xs | 父元素内宽<768px时,每行渲染多少空间 | `number` | `1` | +| sm | >=768px | `number` | `2` | +| md | >=998px | `number` | `3` | +| lg | >=1200px | `number` | `4` | + +### SearchForm Slots: + +| 名称 | 说明 | +| :------: | :---------------------------------------------------------------------: | +| collapse | 折叠按钮,参数为 `{collapse:展开为true否则false,handle:展开折叠的方法}` | + +### SearchFormItem Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| :---: | :---------------------------: | :------: | :-------: | +| label | 等同于`el-form-item`的`label` | `string` | - | diff --git a/docs/frontend/components/upload-file.md b/docs/frontend/components/upload-file.md new file mode 100644 index 0000000..cdbc1e0 --- /dev/null +++ b/docs/frontend/components/upload-file.md @@ -0,0 +1,31 @@ +# Upload File + +集成七牛云直传,需要配合后端使用。支持图片、word、pdf、ppt、rar、excel、txt、zip类型的文件预览(使用kkFileView)。 + + + +### 引入: + +`@/components/UploadFile` + +### 使用: +```html + +``` + +### UploadFile Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| :------: | :--------------------: | :---------------: | :------: | +| disabled | 等同于`el-upload` | `boolean` | - | +| multiple | 等同于`el-upload` | `boolean` | `true` | +| fileList | 等同于`el-upload` | `array` | `[]` | +| limit | 等同于`el-upload` | `number` | `10` | +| maxSize | 单次上传文件的最大大小 | `number / string` | `'10MB'` | + +### UploadFile Events: + +| 事件名称 | 说明 | 回调参数 | +| :------: | :--------------------------: | :---------------: | +| remove | 移出不是本次上传的文件时触发 | `{url}` | +| success | 上传成功后触发 | `(file,response)` | diff --git a/docs/frontend/deploy.md b/docs/frontend/deploy.md new file mode 100644 index 0000000..887df37 --- /dev/null +++ b/docs/frontend/deploy.md @@ -0,0 +1,34 @@ +# 构建和发布 + +## 构建 + +当项目开发完毕,只需要运行一行命令就可以打包你的应用: +```shell script +# 默认环境为 production +npm run build +``` + +构建打包成功之后,会在根目录生成`dist`文件夹,里面就是构建打包好的静态文件。 + +如果需要指定`dist`目录等,则需要通过`vue.config.js`的`outputDir`进行配置。 + +## 发布 + +如果静态文件不是部署在根目录下,比如想部署在 `/app` 下,那么需要将 `@/config/index.js` 中的 `contextPath` 改为 `/app/`。 + +想在 `js`中引入的话,可以直接使用 `process.env.BASE_URL` 拿到`contextPath`。 + +如果是在 `html` 中引入的话,是 `<%= BASE_URL %>` 的形式,这是 `ejs` 的语法。 + +::: warning 注意 +`contextPath` 应始终以 `/` 开头,以 `/` 结束。 +::: + +## 路由模式 + +项目提供了动态修改路由模式的功能,只需要修改 `@/config/index.js` 中的 `routerMode` 即可。 + +当路由模式为 `'history'` 时,需要服务器提供支持。以 `nginx` 为例,需要在配置中补上: +```shell script +try_files $uri $uri/ /index.html; +``` diff --git a/docs/frontend/global-methods/bottom-tip.md b/docs/frontend/global-methods/bottom-tip.md new file mode 100644 index 0000000..fd78756 --- /dev/null +++ b/docs/frontend/global-methods/bottom-tip.md @@ -0,0 +1,6 @@ +# 底部警告信息弹框 + +### 使用: +```js +this.$bottomTip('hello') +``` diff --git a/docs/frontend/global-methods/guide.md b/docs/frontend/global-methods/guide.md new file mode 100644 index 0000000..6804d19 --- /dev/null +++ b/docs/frontend/global-methods/guide.md @@ -0,0 +1,56 @@ +# 用户导航 + +这是在driver.js的基础上改造来的。 + +### 使用: + +- 在 `@/mixins/guide/data` 下创建导航步骤,例如 `test.js`。 + +- 在需要导航的路由页面里引入 `@/mixins/guide`,并混入 `mixins: [guide.test]` + +```js +//配置导航 +this.$guide.config(config) + +//开始一个导航 +this.$guide(start,steps,[,beforeExist]) + +//退出导航 +this.$guide.exit() +``` + +### $guide.config(config) + +- config,所有可配置项如下: +```js +{ + stageBackground: "#ffffff",//弹框背景颜色 + doneBtnText: "完成", //完成按钮的文字 + closeBtnText: "关闭", //关闭按钮的文字 + nextBtnText: "下一步", //下一步按钮的文字 + prevBtnText: "上一步", //上一步按钮的文字 +} +``` + +### $guide(start,steps,[,beforeExist]) + +- `start` : `number / string`,从第几个步骤开始,`number` 型从0开始,`string` 型可以为 `'first'` 或 `'last'`。 + +- `step` : `array`,导航步骤数组,所有可配置项如下: +```js +{ + ...config, + element: string, 用于querySelector, + content: string, 弹框内容,可以使用html, + forceShowPrevBtn: boolean, 是否强制显示上一步按钮 + forceShowNextBtn: boolean, 是否强制显示下一步按钮 + onPrevious: function, 跳转到上一个导航步骤前触发,返回false或Promise.reject()来阻止跳转 + onNext: function, 跳转到下一个导航步骤前触发,返回false或Promise.reject()来阻止跳转 +} +``` + +- `beforeExist` : `function`,退出导航前触发,回调参数是一个 `boolean`,表示当前是否是最后一个步骤,返回 `false` 或 `Promise.reject()` 来阻止退出。 + +### $guide.exit() + +退出导航,会触发 `beforeExist` 钩子 diff --git a/docs/frontend/global-methods/image-viewer.md b/docs/frontend/global-methods/image-viewer.md new file mode 100644 index 0000000..b4c5f6e --- /dev/null +++ b/docs/frontend/global-methods/image-viewer.md @@ -0,0 +1,17 @@ +# 图片预览 + +### 使用: + +```js +//开始预览 +this.$image({index, urlList}) + +//退出预览 +this.$image.close() +``` + +### $image({index, urlList}) + +- `index` : `number`,当前图片在图片数组中的下标。 + +- `urlList` : `array`,需要预览的图片的url数组 diff --git a/docs/frontend/global-methods/puzzle-verify.md b/docs/frontend/global-methods/puzzle-verify.md new file mode 100644 index 0000000..21df8a4 --- /dev/null +++ b/docs/frontend/global-methods/puzzle-verify.md @@ -0,0 +1,11 @@ +# 拼图滑块验证 + + + +### 使用: + +```js +this.$puzzleVerify().then(...).catch(...) +``` + +返回一个 `promise`,如果验证失败会 `reject`,否则 `resolve` diff --git a/docs/frontend/global-methods/signature.md b/docs/frontend/global-methods/signature.md new file mode 100644 index 0000000..5aac4d7 --- /dev/null +++ b/docs/frontend/global-methods/signature.md @@ -0,0 +1,21 @@ +# 手写签名 + +### 使用: + +```js +//开始签名 +this.$signature({image, lineWidth, lineColor, onConfirm) + +//退出签名 +this.$signature.close() +``` + +### $signature({image, lineWidth, lineColor, onConfirm) + +- `image` : `string`,需要回显的签名图片的src。 + +- `lineWidth` : `number`,线的宽度,默认 `6` + +- `lineColor` : `string`,线的颜色,默认 `'#000000'` + +- `onConfirm` : `function`,签名完毕后触发,回调参数为签名图片的base64 diff --git a/docs/frontend/layout.md b/docs/frontend/layout.md new file mode 100644 index 0000000..ae37047 --- /dev/null +++ b/docs/frontend/layout.md @@ -0,0 +1,52 @@ +# 布局 + +此布局是在vue-element-admin的基础上改造而来。 + +实际上这个布局算是二级路由,一级路由是App.vue,这就是为什么经常会看到路由会这么写的原因: +```json +{ + "path": "/", + "component": Layout, + "children": [ + { + "path": "index", + "name": "index", + "component": Page, + "meta": {"title": "首页"} + } + ] +} +``` +`Layout` 填充到 `App.vue` 里的 ``,而真正的路由页面 `@/views/index` 则填充到 `Layout` 里的 ``。 + +项目中没有用到 `Layout` 的页面只有 `@/router/constant/modules/app.js` 里的 `login`、`403`、`404` 这三个。 + +另外可以发现 `App.vue` 使用了 ``,这是为了从 `403`、`404` 返回时能保存之前打开的标签页。 + +## 多页签 + +增加了平滑滚动功能,增加了快捷键功能:`ctrl + → 下一个页签`、`ctrl + ← 上一个页签` + +::: warning 注意 +多页签在 启用 / 停用 之间切换时,之前缓存的页签实例会清空,也就是说再次打开时会是新的页面 +::: + +## 侧边栏 + +重复点击菜单可刷新路由,折叠时可以选择是否在折叠菜单上显示父级。 + +侧边栏的滚动分两种情况,一种是整体的滚动,这是用 `` 做的,不过缺点就是移动端体验不好。 +另一种是弹出菜单的滚动,这是用 `css` 做的,不用 `` 是因为没办法避免bug,具体原因可以去看element-ui的 `submenu #handleMouseleave`。 + +## 全局页脚 + +只有使用了 `Layout` 组件的路由页面才会有这个页脚。 +这里的实现比较特别,由于路由页面被 `` 包裹,需要将页脚的dom插入到 `` 的dom中,所以使用了这种方法: +```javascript +const FooterConstructor = Vue.extend(Footer) +const footerInstance = new FooterConstructor().$mount() +this.$refs.scrollbar.$refs.wrap.appendChild(footerInstance.$el) +``` +至于为什么不用函数式组件,是因为我还不知道怎么样拿到一个函数式组件的dom + + diff --git a/docs/frontend/new.md b/docs/frontend/new.md new file mode 100644 index 0000000..2ef5755 --- /dev/null +++ b/docs/frontend/new.md @@ -0,0 +1,15 @@ +# 新增页面 + +1. 把数据请求api创建出来,建议在 `@/api`下根据模块区分。 + +2. 创建路由页面,建议在 `@/views` 下根据模块区分。 + +3. 如果页面过大过复杂,建议按功能拆分,放在当前页面的文件夹里。 + +4. 独有的样式同样放在当前页面的文件夹里,能公用的提取到 `@/assets/styles` 里。 + +5. 创建路由,根据是否需要鉴权,在 `@/router/authority/modules` 或 `@/router/constant/modules` 下创建,这两个文件夹下的js会被自动导出。 + +6. 如果需要创建vuex模块,请在 `@/store/modules` 下创建,同样的,该文件夹下的js会被自动导出。 + +7. 如果页面之间存在公共组件,建议抽取出来,根据业务耦合度拆分至 `@/components` 或 `@/bizComponents` diff --git a/docs/frontend/permission.md b/docs/frontend/permission.md new file mode 100644 index 0000000..09b1f8a --- /dev/null +++ b/docs/frontend/permission.md @@ -0,0 +1,16 @@ +# 权限 + +项目使用基于资源url的形式来实现权限控制,说白点就是用户的所有操作都可以用一个url来标识。 + +鉴权方法为 `@/util/auth.js #auth`。 + +鉴权流程: +1. 如果用户的`admin` 字段为1,那么直接放行。 + +2. 如果访问的 `url` 不在总权限树内,说明该操作无需权限,放行。 + +3. 如果访问的 `url` 在用户的权限树内,说明有权限,放行。 + +4. 否则拦截,跳转至403页面。 + +当然前端的权限控制只是过滤一小部分,真正的工作还是由后端完成。 diff --git a/docs/frontend/plugins.md b/docs/frontend/plugins.md new file mode 100644 index 0000000..5b8a0ec --- /dev/null +++ b/docs/frontend/plugins.md @@ -0,0 +1,18 @@ +# 插件 + +## canvas动画 + +所有动画位于 `@/plugin/canvasAnimation`下,使用 `new Animation(canvas)`的方式来创建一个动画。 +想停止的话调用 `Animation.stop()` 即可。 + +## 图片压缩 + +支持 `png`、`jpg` 两种格式的图片,使用方法参考 `@/views/example/developingTest/components/ImageCompressTest.vue`。 + +::: tip +由于是以 `worker` 的形式调用,所以需要准备 `cjpeg.min.js` 和 `pngquant.min.js`,这两个文件都放在项目的 `public`下。 +::: + +## 其他 + +此外项目中还有 `live2d` 和 `webgl` 两个插件,有兴趣的可以自行查看。 diff --git a/docs/frontend/router.md b/docs/frontend/router.md new file mode 100644 index 0000000..ace3536 --- /dev/null +++ b/docs/frontend/router.md @@ -0,0 +1,158 @@ +# 路由 + +## 路由配置项 + +路由配置项不光参与路由的生成,也参与侧边栏、搜索结果的生成。 + +### Route Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| ---------- | ---------------------------------------------------- | ------------------- | ----- | +| hidden | 是否在侧边栏中显示 | `boolean` | - | +| alwaysShow | 是否总是把只有一个子级的菜单以嵌套模式在侧边栏中展示 | `boolean` | - | +| sort | 侧边栏的排序值,值越小越靠前 | `number` | 10000 | + +### Route.meta Attributes: + +| 参数 | 说明 | 类型 | 默认 | +| ------------ | ------------------------------------------------ | --------- | ----------------------- | +| title | 路由在侧边栏、面包屑、页签、搜索结果中的显示名称 | `string` | - | +| icon | 图标名,支持svg-icon、el-icon | `string` | - | +| affix | 是否在多页签中固定显示 | `boolean` | - | +| noCache | true时缓存页面 | `boolean` | - | +| activeMenu | 侧边栏当前激活菜单的index | `string` | - | +| noAuth | true时路由不需要鉴权 | `boolean` | router/constant下为true | +| iframe | 需要打开的iframe的地址 | `string` | - | +| isDetailPage | 是否是详情页 | `boolean` | - | + +::: tip 注意 +路由meta上的affix、noAuth、noCache会被子路由继承,优先使用子路由的值 +::: + +## 页面缓存 + +先总结一下路由页面被缓存的条件: +- 启用了多页签 +- `(route.name || route.meta.isDetailPage) && route.meta.noCache && !route.meta.iframe` + +通常情况路由想做缓存都是通过 ``,但是如果是像 `/edit/1`、`/edit/2` 这样的共用路由页面的详情页的话, +`` 就满足不了需求,因为它是通过组件的 `name` 来区分组件的。 +所以项目中仿照 `` 写了 ``,可以根据当前路由的路径来区分组件。 + +除此之外还有个问题,在共用了同一个组件的路由之间跳转的话,组件会被复用,假如有以下路由: +```js +const component={template:``, data: ()=> ({data:1})} + +const routes = [ + { path: '/foo', component }, + { path: '/bar', component } +] +``` +先访问 `/foo`,然后将输入框的值改为100,再访问 `/bar` ,会发现输入框的值还是100。 +所以在 `router.beforeEach` 中做了判断,如果跳转前后的路由的 `meta.isDetailPage` 均为 `true` 的话,那么借助 `/redirect` 跳转一次,从而避免组件复用的问题 + +::: warning 注意 +如果不使用meta.isDetailPage的话,需要缓存的页面的 `name` 必须和路由的 `name` 一致 +::: + +## 路由白名单 + +在 `@/router/index.js` 中有这么一句: +```js +const whiteList = transformWhiteList(['/login', '/register', '/404', '/403']) +``` +这个 `whiteList` 就是白名单,里面的值会被转为正则表达式,详细请查看[path-to-regexp文档](https://github.com/pillarjs/path-to-regexp)。 +被`whiteList` 匹配的路由不需要验证,直接放行。 + +## 首屏加载效果 + +想体验的可以把 `network` 设为 `slow 3g` 就可以在在线实例看到效果。 + +原理很简单,在 `index.html` 里有这么一段: +```html +
+
+ +

资源加载中......

+
+
+``` +在 `vuejs` 初始化完成后,`app` 里的内容会被替换,从而实现加载效果。 + +## 骨架屏 + +通常情况下,路由组件都是以 `import(...)` 的形式异步引入, +如果想让路由在加载异步组件时显示,可以使用以下方式: +```js +function lazyLoadView(component) { + const AsyncHandler = () => ({component, loading: Skeleton}) + return Promise.resolve({ + functional: true, + render(h, {data, children}) { + return h(AsyncHandler, data, children) + } + }) +} + +//将路由配置中的component项改为以下形式 +component: () => lazyLoadView(import(...)) +``` + +关于 `AsyncHandler` 的更多选项,可以查看[官方文档](https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%A4%84%E7%90%86%E5%8A%A0%E8%BD%BD%E7%8A%B6%E6%80%81) + +## 过渡动画 + +正常 `` 使用过渡动画的方法应该是这样的: +```html + + + + + +``` + +但是由于项目中使用了自定义的 ``,所以就变成这样的: +```html + + + + + +``` + +具体原因是 `` 中的代码硬编码了 ``,导致如果按照往常写法的话,过渡动画不会生效。 + +项目中是根据页签的前后位置来决定路由动画的,比如从前面的页签跳转到后面的,那么动画是从左滑出,反之是从右滑出。 + +::: warning 注意 +只有在启用了多页签的时候才会有上面的效果,否则默认是 `el-fade-in-linear` 动画。 +::: + +## iframe + +只需要按如下配置即可打开一个iframe: +```json +{ + "path":"/baidu", + "meta":{ + "iframe":"https://www.baidu.com" + } +} +``` + +当向上面的路由跳转时,会隐藏路由页面,展示 `