基于!!vue2!!开发的后台管理系统
1.搭建项目
vue create 项目名(小写)
项目配置项勾选linter/formatter=>勾选lintonsave=>vscode的settings.json修改vscode默认配置如下:
"editor.codeActionsOnSave": {
//保存自动fix修复
"source.fixAll": true
},
// 选择lint禁用format
"editor.formatOnSave": false,
//至此已经做到保存自动lint报错并且fix修复错误
引用:关于使用editorconfig覆盖vscode默认配置:
此文件的作用是为了防止团队协作时大家所用ide不同导致代码规范不同每次合并代码时带来大量的并没有变化的代码合并和不必要的冲突。 安装插件(webstorm 跳过) 此处以 VS Code 为例
去商店中搜索 EditorConfig for VS Code 进行安装,这样 VS Code 就会优先根据项目根目录的.editorconfig 文件对缩进之类风格进行配置,覆盖 VS Code 默认配置。
EditorConfig 插件会从文件所在目录开始逐级向上查找 .editorconfig,直到到达根目录或者找到包含属性 root=true 的 .editorconfig 文件为止。
当找到所有满足条件的 .editorconfig 配置文件后,插件会读取这些配置文件的内容,距离文件路径最短的配置文件中的属性优先级最高,同一个文件按照从上到下方式读取,底部定义的同名属性优先级要高于顶部定义的。
大部分编辑器都有这个插件,即使团队成员使用不同的 IDE,也可以很好的统一代码风格。
只要保证.editorconfig 这个文件一直即可
2.初始化项目
2.1 整理目录:清除默认生成的组件,整理根组件,修改路由文件,新建utils工具目录,新建api接口目录,如果使用vuex,新建store仓库目录
2.2 配置文件:
vue.config.js:
lintOnsave:true//启用保存报lint错误
devServer:{
client:{
overlay:false//关闭遮罩报错
}
}
babel.config.js:
如果项目使用vant/element-ui组件库少部分组件,想要按需导入,需要先在这里配置插件:
//vant:
plugins: [
['import', { //先下包 npm i babel-plugin-import -D
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
//element-ui:
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[ "component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
] ] }
//配置插件之后,再不必如下手动按需导入:
//import Button from 'vant/lib/button';
//import 'vant/lib/button/style';
//Vue.use(Buuton)
//可以直接:
//import { 组件名 } from 'vant';
//Vue.use(组件名)
//配置插件之后,无法再全部导入
.eslintrc.js:
'vue/multi-word-component-names':'off'//关闭组件名称遵循多词格式的规则报错
3.构建utils
3.1 封装storage
const tokenKey = 'token'
export function setToken(token) {
localStorage.setItem(tokenKey,token)
}
export function getToken(){
localStorage.getItem(tokenKey)
}
export function delToken(){
localStorage.removeItem(tokenKey)
}
3.2封装axios
//先导包 npm i axios
import {getToken} from '@/utils/storage'
import store from '@/store'
import router from '@/router'
//封装axios
import axios from 'axios'
const request = axios.create({
baseURL:'当前项目基地址',
timeout:5000
})
//请求拦截器(请求发送之前拦截处理)
request.interceptors.request.use(config=>{
//配置token
config.headers.Authorization = getToken()//注意与接口文档规定的token格式一致
//config.headers.Authorization = store.state.token//token可以从浏览器取(localStorage)也可以从vuex取(内存,更快,不刷新页面只需要从localStorage读取一次token)
return config
},error=>{
//一般无请求错误
return Promise.reject(error)
})
//响应拦截器(响应发送之后拦截处理,无论是请求拦截还是响应拦截处理都是替浏览器执行处理)
request.interceptors.response.use(response=>{
//可以进行数据剥离,仅发送浏览器所需的数据
return response
},error=>{
//可以统一错误处理
if(error.response) console.log(error)
//处理token过期
if(error.response.status===401) {
delToken()
router.push('/login')
}
return Promise.reject(error)
})
3.3 封装组件库(vant2/element-ui)
//vant2:适用于vue2
//npm i vant@latest-v2 -S
3.3.1 vant2按需导入
//见本文2.2配置文件
3.3.2 vant2全部导入
import Vue from 'vue'
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
3.3.3 element-ui按需导入/全部导入
https://element.eleme.cn/#/zh-CN/component/quickstart
4. 组件库主题色定制
4.1 vant主题色定制
第一步: 修改babel.config.js
plugins: [
[ 'import', {
libraryName: 'vant',
libraryDirectory: 'es',
// 修改这里=》指定样式路径
style: (name) => `${name}/style/less`,
}, 'vant', ],
],
第二步:配置vue.config.js
css: {
loaderOptions: {
less: {
// 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
lessOptions: {
modifyVars: {
// 直接覆盖变量
blue: '#FA6D1D',
//green: '#07c120'
//'text-color': '#111',
//'border-color': '#eee',
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
//hack: `true; @import "your-less-file-path.less";`,
}, }, }, }, }
4.2 element-ui主题色定制
https://element.eleme.cn/#/zh-CN/component/custom-theme
使用官网在线主题编辑器,选好color-primary主题色一栏的颜色,下载压缩包,解压到项目下src文件夹,将其中的css文件导入入口(一般为main.js)
5.封装接口
将接口文档中的接口按照功能模块封装入不同的js文件内,比如登录功能模块的接口封装入login.js
import request from '@/utils/request.js'
//登录
export function loginApi() {
return request.post('path',{body参数}) //登录要返回响应获取token
}
//退出登录
export function exitApi() {
request('path')
}
//获取用户信息
export function getUser(){
return request('path')
}
6.配置路由与守卫(router.js)
//1级路由登录与主页的出口router-view配置在根组件中,主页下的两个嵌套路由出口router-view配置到主页组件中
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'
Vue.use(VueRouter)
//路由懒加载
const 组件名 = ()=>import('组件路径')
...
const routes = [
//重定向
{path:'path',redirect:'path'},
{
path:'path',
component:组件名,
//嵌套路由
children:[
{path:'path',component:组件名}
]
},
{path:'*',component:notFound组件}
]
const router = new VueRouter({
routes
})
//设置全局前置守卫
const whiteList(['path','path'])
router.beforeEach((to,from,next)=>{
const token = store.state.token//如果是分模块的vuex,模块名当做state属性使用,比如user模块下的state有token,访问token:store.state.user.token if(token) next() else if(whiteList.includes(to.path)) next() else next('/login') }) //导出路由实例 export default router //只导出一个,使用默认导出,导出多个使用按需导出,导出谁就export谁
7.登录组件构建
登录要获取用户输入的用户名与密码,用了element-ui的el-form、el-input、el-button组件,el-form-item设置v-model,el-form设置model获取所有表单域的v-model,el-form设置rules校验规则,el-form-item设置prop校验项,通过blur事件触发单个表单域校验,提交时还要通过el-form的validate进行一次全部表单域校验,设置了reset按钮,点击触发el-form的resetFields()方法初始化所有设置了校验项的表单域,又用了el-card,设置了插槽标题,想要给插槽标题设置样式,但是在登录组件中,只能给其中的组件的根设置样式,比如el-card,而不能给el-card内部元素设置样式,因为组件样式被scoped修饰了,这里需要用到深度作用选择器::v-deep给el-card内部元素加样式,,比如.a ::v-deep .b ,效果相当于 .a[data-v-xxx] .b,最后可以直接给card卡片加样式,调整整体放置位置,点击登录按钮调用登录接口,要发送ajax请求获取token,将获取到的多个组件要用的token存储到vuex中,并且存到浏览器中(localStorage),因为请求获取到的数据要存储在vuex里,所以请求数据的操作也要在vuex的actions里。然后通过路由守卫的验证,路由导航到主页。
8.主页组件构建
整体上利用el-container左右布局,左侧aside,右侧再放一个el-container,里面放header和main,main里放主页嵌套路由的出口
注意:el-container的子元素只能是el-header/el-aside/el-main/el-footer,四者的父元素也只能是 el-container,以上组件采用了 flex 布局,使用前请确定目标浏览器是否兼容。
9.主页下嵌套路由构建
9.1 数据可视化组件构建
使用echarts步骤:
1.导入echarts的js
2.在组件中创建DOM容器
3.实例化echarts:const echarts = echarts.init(DOM容器)
4.echarts.setOption({配置项...})//使用配置项与数据渲染容器
9.2数据管理组件构建(增删改查)
使用了el-card,title插槽用了面包屑Breadcrumb图标写法,用el-button的primary类型写了添加按钮,
点击添加按钮修改drawerFlag显示嵌套了el-form的抽屉drawer,填充el-form,逐个校验,点击提交,
进行全部校验,发送ajax请求往数据库里添加数据,再发送请求重新拉取列表数据,修改本地data变量,
进而修改table渲染,最后修改drawerFlag关闭drawer,el-drawer还写了:before-close="beforeClose",
在beforeClose里通过this.$confirm().then.catch弹窗询问是否确认关闭drawer,
then里修改drawerFlag并且修改el-drawer的title为'添加数据';el-card的body区域用了el-table渲染列表数据,
用el-button的text类型搭配icon写了预览、修改、删除按钮,点击预览修改drawerFlag1,
划出一个嵌套了富文本编辑器的drawer抽屉;点击修改按钮,修改drawerFlag并且将drawer的title从添加数据
修改到编辑数据,预览与编辑都需要通过el-form中的slot-scope="scope"接收从el-form组件内回传的scope数据,
这里面包含了表格table里的当前行对象row和table当前行对应的列表数据元素在列表中的索引$index,通过row.id
修改el-drawer中的el-form的model属性绑定的data变量form与表格当前行数据一致,实现显示回显所点击的
表格行数据的el-form所在的el-drawer抽屉的效果,点击编辑drawer中的提交,发送ajax请求修改数据库,再发送ajax
请求拉取修改后的数据列表修改本地data变量list,进而修改绑定了list的table渲染,注意异步;点击删除
使用this.$confirm().then(()=>{}).catch(()=>{}),弹框确认删除操作,then里发送ajax请求,删除数据库中的数据,
重新拉取数据列表修改本地data变量list,进而修改渲染绑定了list的table,用了Pagination组件进行分页渲染,
v-bind修饰current-page.sync双向绑定默认值为1的currentPage变量,给pagination绑定current-change事件,
传递currentPage变量作为回调函数的参数,在回调函数里发送ajax请求获取当前页的数据列表渲染table,
实现分页渲染效果。
总结:利用vue组件化开发单页应用程序,可以笼分为三部分:页内跳转-路由、与服务器的互动-ajax、业务逻辑(利用组件库实现),书写项目的顺序笼分为4步:项目初始化=>准备工具=>封装接口=>业务实现,项目初始化包括:整理目录、配置文件,准备工具包括:封装localStorage、封装axios、导入组件库(element-ui/vant),然后按照接口文档将所有接口按照功能模块分别封装,之后从登录开始逐个组件开始,主要依赖组件库实现业务逻辑