vue-vueadmin记录
vue-vueadmin记录
相关资料
- 官方资料
- GitHub - https://github.com/PanJiaChen/vue-element-admin/blob/master/README.zh-CN.md
- 中文文档 - https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84
- 示例 - https://panjiachen.gitee.io/vue-element-admin/#/dashboard
- vue 文档 - https://cn.vuejs.org/v2/guide/
- element 文档 - https://element.eleme.io/#/zh-CN/component/layout
- vuex 文档 - https://vuex.vuejs.org/zh/guide/
- 手摸手,带你用vue撸后台 系列 (不错) - https://juejin.im/post/59097cd7a22b9d0065fb61d2
- vue-element-admin 技术栈 - https://learnku.com/articles/20050?order_by=vote_count&
TODO
- webpack 打包
- 全局变量或函数
vscode 插件
- Vuetur
- vue
- ESLint
chrome 插件
安装完后插件栏有个 vue icon 出现, 按 f12 调出调试工具, 顶栏有个 vue 的选项.
取消 eslint 校验
官方文档 - https://eslint.org/docs/rules/
去掉 缩进校验
.eslintrc.js
文件中的 'indent': [2, 2, {
修改为 'indent': [0, 0, {
就可以 4 个空格为缩进
去掉 单引号 双引号 校验
参考: https://eslint.org/docs/rules/quotes
.eslintrc.js
文件中的 'quotes': [2, 'single',
修改为 'quotes': [0, 'single',
去掉 代码结尾 分号 校验
参考:
.eslintrc.js
文件中的 'semi': [2, 'never'],
修改为 'semi': [0, 'never'],
去掉 no use 校验
.eslintrc.js
文件中的文件中的 'no-unused-vars': [2, {
修改为 'no-unused-vars': [0, {
去掉 空行 校验
.eslintrc.js
文件中的文件中的 'no-multiple-empty-lines': [2, { 'max': 1
修改为 'no-multiple-empty-lines': [2, { 'max': 9999
去掉 对象构建 最后一个 逗号 校验
.eslintrc.js
文件中的文件中的 'comma-dangle': [2,
修改为 'comma-dangle': [0,
生命周期
- 详解 Vue 生命周期实现 - https://juejin.im/post/5c6d48e36fb9a049eb3c84ff
查找调用栈
在 chrome 中按 F12 键, 在 sources 下 ctrl + shift + F, 查找日志, 然后设置断点.
环境变量配置
配置文件为 .env.xxx
环境变量必须以
VUE_APP_
为开头。如:VUE_APP_API
、VUE_APP_TITLE
1
console.log(process.env.VUE_APP_xxxx)
修改配置文件后必须重新 npm run dev 才生效
跨域配置
- 使用vue-element-admin框架调用后端接口及跨域问题 - https://blog.csdn.net/ywdhzxf/article/details/90518807
在 vue.config.js 文件中
1 | proxy: { |
webpack.config.js
import 别名设置
1 | configureWebpack: { |
状态存储 Vuex
参考: https://vuex.vuejs.org/zh/guide/state.html
访问数据
通过在根实例中注册 store
选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store
访问到
Element UI
页面数据使用
- vuex 中关于 mapGetters 的作用 - https://www.cnblogs.com/crazycode2/p/7636082.html
ui 使用多语言
参考: https://codeday.me/bug/20190430/1010561.html
在 main.js 中引入多语言
1 | import locale from 'element-ui/lib/locale/lang/en' |
踩坑
报错: The “MyComponent” component has been registered but not used
没有使用组件命名不正确
1
2
3
4 import MyComponent from './components/MyComponent'
// 使用时的命名必须是 my-component, 不能用驼峰命名, 必须全小写, 用 - 分割. 绑定值也一样
<my-component :arg1="123" :is-show="isShow" :arg3="'hello'" @on-my-notify="onMyNotify666" />
报错: Syntax Error: SyntaxError: Assigning to rvalue
参考: https://blog.csdn.net/u014182411/article/details/80071198
html的模板中 引用的值 如: v-module 绑定的属性并没有在 data 属性中定义
报错: Attribute ‘fileNameTitle’ must be hyphenated
参考: https://blog.csdn.net/qq_35366269/article/details/90644180
原因
出现该错误的原因是组件的属性fileNameTitle使用了驼峰命名法,导致ESLint 检测出语法错误
解决办法:
将fileNameTitle改为file-name-title即可
1
2
3 <my-component :arg1="123" :isShow="isShow" :arg3="'hello'" @onMyNotify="onMyNotify666" />
<!-- 修改为: -->
<my-component :arg1="123" :is-show="isShow" :arg3="'hello'" @on-my-notify="onMyNotify666" />
组件
命名方式
传参 props
1 | props: { |
监听 watch
1 | watch: { |
参考报错: [组件赋值 object 第一次不生效问题](#组件赋值 object 第一次不生效问题)
静态加载
动态加载
- Vue动态组件和异步组件 - https://segmentfault.com/a/1190000018018502
- 官网: 动态组件 & 异步组件 - https://cn.vuejs.org/v2/guide/components-dynamic-async.html
异步加载
- Vue中的异步组件 - https://juejin.im/post/5c3c7435e51d4551cd71cf5c
- 官网: 动态组件 & 异步组件 - https://cn.vuejs.org/v2/guide/components-dynamic-async.html
父组件控制子组件显示隐藏
不能同步一个值
tree
自定义唯一 key
node-key
,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的。
半选状态
this.checkStrictly = false
代码动态设置时, 选中子节点时, 父节点才有半选状态
date-picker
日期拾取禁用 > 今天
加入 disabledDate 属性
1
2
3
4
5
6
7
8
9data () {
return {
datePickerOptions: {
disabledDate (date) { // 增加 disabledDate 字段
return date > new Date()
}
}
}
}
mock 服务器
使用 json 当做临时数据库
使用 const fs = require('fs')
io 本地文件即可
hot reload 忽略 部分文件监听
修改 mock-server.js 增加忽略文件
1
2
3
4
5
6
7
8
9
10
11
12// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
}).on('all', (event, path) => {
//修改为
// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: [/mock-server/, /fakedb/], // 这样 fakedb 目录下的文件就不会被监听
ignoreInitial: true
}).on('all', (event, path) => {重启 mock. done
踩坑
在 mock 目录下, 文件变化会导致 hotload 重启服务器
通常在使用 [使用 json 当做临时数据库](#使用 json 当做临时数据库) 是 io 文件后, 回导致重启服务器, 导致服务器 token 被重置, 解决办法: hot reload 忽略 部分文件监听
权限验证
- 权限验证 (静态权限) - https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/essentials/permission.html#%E9%80%BB%E8%BE%91%E4%BF%AE%E6%94%B9
- 手摸手,带你用vue撸后台 系列二(登录权限篇) (动态权限) - https://juejin.im/post/591aa14f570c35006961acac
添加路由
一级节点添加子节点
1 | { |
非一级 节点下添加 子节点
1 | { |
index222.vue 的内容, 非一级节点 都可以使用这个模板
1 | <template> |
- 如果没有
<router-view />
控件, 那么该节点之下的所有子节点加载的页面都不是对应的页面, 而是加载~/views/id-check/index222
这个页面. ( 被这个坑了有点久 )
动态路由
- 将前端的 路由 丢个后端, 后端鉴权后获取该用户可访问的路由表通过 json 方式发给前段, 前端在转成路由,
router.addRoutes(accessRoutes)
的方式动态添加进去.
运行时 惰性加载 import 问题
webpack 打包不能再运行时 import 一个变量, 会报错找不到页面:
__webpack_require__("xxx"
, 只能 import 一个常量值, 所以曲线救国的方式是用一个 map 去映射1
2
3
4
5
6
7
8const routerMap = {
'layout': () => import('@/layout'),
'~/views/permission/page': () => import('~/views/permission/page'),
'~/views/permission/directive': () => import('~/views/permission/directive')
}
item.component = routerMap[item.component] // 正确姿势
// item.component = () => import(item.component) // 报错, 运行时变量参考
- vue 异步组件采用参数路径报错 - https://segmentfault.com/q/1010000012485066
增加页面
因为 [运行时 惰性加载 import 问题](#运行时 惰性加载 import 问题) 的原因, 所以每次添加页面需要 服务端路由表增加一个 router, 在 客户端 map 映射表增加一个页面映射
服务器下发路由表 component 值问题
下发的路由中的 component 字段不要有 @
字符, 比如 component: '@/views/excel/select-excel'
, 用 mock 下发时报错, 换别的语言的服务器应该不会有问题,
vue.config.js 加个别名
1 | configureWebpack: { |
就可以这样下发 json : component: '~/views/excel/select-excel'
踩坑
从后台获取路由Map后,前台转route的时候报错
参考: https://github.com/PanJiaChen/vue-element-admin/issues/2381
报错: __webpack_require__("xxx"
1 | vue-router.esm.js:1897 Error: Cannot find module 'function () { |
webpack 打包不能再运行时 import 一个变量, 参考: [运行时 惰性加载 import 问题](#运行时 惰性加载 import 问题)
报错: must be accessed with "$data."
参考: 从后台获取路由Map后,前台转route的时候报错 - https://github.com/PanJiaChen/vue-element-admin/issues/2381
将 服务器下发的路由 转换一下
自定义代理
允许将一个 请求白名单 代理请求到指定的 服务器
在 环境配置文件 .env.development 增加一个 api 标记和指定的服务器
1
VUE_APP_DEBUG_API = '/debug-api'
暂时不想写
webpack 打包
部署
https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84
1 | # clone the project |
protobuf 接入
- 如何在前端中使用protobuf(vue篇) - https://www.fengxianqi.com/index.php/archives/129/
流程
安装 pb 相关库
1
npm install --save protobufjs protobufjs/light
将 xxx.proto 生成为 js 文件
1
npx pbjs -t json-module -w commonjs -o src/proto/proto.js proto/*.proto
将此命令加入 package.json, 方便以后生成
1
2
3
4
5"scripts": {
"serve": "vue-cli-service serve",
...
"proto": "npx pbjs -t json-module -w commonjs -o src/proto/proto.js proto/*.proto"
},
a
js 语法糖
获取对象中的某个属性
1 | const response = { |
多个 then
- es6中Promise多个then的使用方法 - https://blog.csdn.net/qq575792372/article/details/83901397
踩坑
方法调用参数要一直
不一致会导致调用不到方法
请求 400 错误
可能是请求的参数封装成 json 不对
1
2
3
4
5
6
7
8
9
10 request({
url: ENetCmd.GetPermission,
method: 'post',
data: token
// 修改为
request({
url: ENetCmd.GetPermission,
method: 'post',
data: { token: token, arg1: '666' }
报错: TypeError: undefined is not iterable
报错:
Error in mounted hook: "TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
一般是由于 路由 为 undefined, 导致 vue 读不到, 所以登出时重置路由不能设为 undefined, 设为一个空数组就ok
1
2
3
4
5
6 const mutations = {
CLEAN_ROUTES: () => { // 不能置为 undefined, 否则读不到路由会报错
state.addRoutes = [] // addRoutes 这个是会被 router.addRoutes(accessRoutes) 进去的
state.routes = []
}
}
使用 el-image 报错: Require self-closing on Vue.js custom components (el-image)
参考: https://github.com/PanJiaChen/vue-element-admin/issues/2400
这个组件是 2.9.0 之后才有, vue-element-admin 使用的是 2.7.0, 升级依稀版本就ok
直接修改 package.json 中的版本
"element-ui": "2.12.0"
, 在执行命令:npm i
访问是报错: Invalid Host header
参考: https://blog.csdn.net/guzhao593/article/details/85918869
在 vue.config.js 文件加入
disableHostCheck: true,
1
2
3
4
5 module.exports = {
devServer: {
disableHostCheck: true, // 加入这个字段
}
}
组件赋值 object 第一次不生效问题
参考: https://blog.csdn.net/qq_37800886/article/details/82220574
解决办法: watch 监听写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 watch: {
userData(newVal, oldVal) {
this.singleData = deepClone(newVal)
}
},
// 修改为
watch: {
userData: {
immediate: true, // 增加这个 immediate 这个属性可以解决 第一次赋值 object 不生效问题
handler(newVal, oldVal) {
this.singleData = deepClone(newVal)
}
}
},
http 请求头 header 上行后变为小写的问题
根据 RFC 2616, 应该 大小写不敏感
js map 的 Object.keys 遍历时, number 类型的 key 变为了 string 类型
用 Number 转换成功 number 类型
1
2
3
4
5
6
7 const permArr = []
Object.keys(this.appPermMap).forEach(key => {
permArr.push({
appId: Number(key), // 这里有个坑,
permissionArr: this.appPermMap[key],
})
})
子节点加载的页面不是对应的页面, 而是父节点的页面
参考: [非一级 节点下添加 子节点](#非一级 节点下添加 子节点)
父节点需要有
<router-view />
控件