目录结构:
- public
- index.html ------------ 主页面
- config.js -------------- 自定义的全局配置页面
- src
- api --------------------- 存放所有的接口
- assets ---------------- 存放所有的静态资源,例如图片、图标、字体图标文件等
- components --------- 存放所有的组件
- directives ------------ 存放所有的自定义指令
- mixins ----------------- 存放全局混入
- filters ------------------ 存放全局过滤器
- styles ------------------ 存放公共样式
- _var.scss ------- 预定义一些变量
- mixins.scss ---- 预定义一些混入
- thems ----------- 主题切换颜色,其中ele.scss放置所有与主题有关的dom节点
- index.scss ----- 样式入口
- store ------------------- 存放所有的全局状态
- router ------------------ 存放所有的路由文件
- plugins ---------------- 存放所有的插件
- utils --------------------- 定义的一些公共方法
- views ------------------- 存放所有的视图
- control.js -------------- 可以作为路由拦截器
- app.vue ---------------- 程序入口
- main.js ----------------- 程序主文件
- .eslintrc.js ------------------- standard模式下的eslint约束规则
- .config.js -------------------- 备份的全局配置文件
- package.js ------------------ 项目信息
- vue.config.js ---------------- webpack配置
功能及注意事项
1、主题切换
主题切换其实是通过点击切换主题风格的按钮时,动态给 body 标签上添加一个 class 类名,然后写不同的类名下dom节点的颜色值来实现的。
// 核心代码
document.getElementsByTagName('body')[0].className = this.activeTheme
注意点是整个项目中涉及到主题切换的dom节点都要放在 /src/styles/theme/ele.scss 中,单个的 blue.scss 就只需要定义不同的颜色变量就可以了。
2、ellint 配置
在 vue create demo 的时候可以选择不同的 eslint 模式,本项目采用 standard 模式,只需要配置 .eslintrc.js 文件就可以使用 eslint 来规范代码,还有两种选择应该是 eslint-config-prettier 和 Airbnb 标准,只需要注意创建项目的时候选的啥,package.json 中就要是啥,不能随便复制别的项目中的 eslint 配置拿来用。
3、css 预编译器
css 预编译器主要有 less / scss / stylus ,我们项目中使用 scss ,同样要注意的是 scss 分为 dart-scss / node-scss ,创建项目的时候选的什么风格就用什么风格,也不能复制不同的 package.json 配置。因为我们的是内网开发,所以我复制别人的 package.json 部分配置,npm i 后就不能正常启动项目。
4、/public/config.js
根目录存放一个备份的 .config.js 文件
5、统一设置 element 组件size
在 plugins 文件夹下新建 element.js 文件
import Vue from 'vue'
import Element from 'element-ui'
import './element-variables.scss' // 重置element风格,如果不需要的话就引入原本的scss文件
Vue.use(Element, {size: 'small', zIndex: 3000})
然后在 main.js 中直接引入
import './plugins/element'
6、整理过滤器
在 filters 文件夹下新建 index.js 文件
import dayjs from 'dayjs // 一个比较好用的时间格式化插件
const timeFilter = value => dayjs(value).format('YYYY-MM-DD HH:MM:SS')
export default {
timeFilter
}
然后在 main.js 中引入并注册为全局过滤器
import filters from './filters'
Object.keys(filters).forEach(filterName => {
Vue.filter(filterName, filters[filterName])
})
7、二次封装el-input组件,默认:trim()、clearable
8、dr-click-input 组件封装
9、dr-mask-search 组件封装
10、按钮、表格的 loading 状态
11、整理弹窗mixin.js文件
主要实现 清除表单验证、重置表单数据、关闭弹窗 的方法
12、修改 open() 的下载方式为 createElement('a') 的方式,避免点击下载时屏幕闪烁
const a = document.createElement('a')
a.setAttribute('href', downUrl)
a.click()
13、路由缓存
<keep-alive :include="cacheViews">
<router=view :key="key" />
</keep-alive>
<script>
export default {
computed: {
key () {
return this.$route.path
}
}
}
</script>
14、.npmrc 文件的作用:项目安装依赖时的下载源地址
registry="http://192.168.1.3:4873"
使用 verdaccio 来从外网向内网更新 node_modules 包
15、消除重复请求
// 在axios请求拦截器中
const CancelToken = axios.CancelToken
const pending = {}
// 生成请求标识
const getRequestKey = (config) => {
const url = config.url
const paramsToString = data => typeOf(data) !== 'string' ? JSON.stringify(data) : data
const params = (config.method === 'get' || config.method === 'GET') ? paramsToString(config.params) : paramsToString(config.data)
return url + config.method + params
}
// 消除重复请求
const removePending (key, isRequest = false) {
if(pendding[key] && isRequest) {
pending[key](key) // 打印出重复的请求
}
delete pending[key]
}
axios.interceptors.request.use(
async config => {
const requestData = getRequestKey(config)
removePending(requestData, true)
config.cancelToken = new CancelToken(c => {
pending[requestData] = c
})
}
return config
)
axios.interceptors.response.use(
response => {
// 移除请求标识
const requestData = getRequestKey(response.config)
removePending(requestData)
},
async error => {
const requestData = getRequestKey(response.config)
removePending(requestData)
}
)
16、数组去重
function arrUnique (arr, fieId = 'id') {
return arr.reduce((all, next) => all.some(item => item[fieId] === next[fidId]) ? all : [...all, next], [])
}
17、生成32位字母+数字的唯一标识
function createRandom () {
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, c => {
let r = Math.random() * 16 | 0
let v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
18、模拟进度条插件 : NProgress
19、token失效响应拦截器中提示消息同时出现多个的问题
在出现401时会清空保存在vuex上的token,那么我们在弹出提示消息前判断一下vuex中是否有token,有的话提示,没有就不显示了,这就可以保障即便多个请求出现401时,也只提示一次。