文章目录
前言(很重要哦)
管理系统后端(java)请参考:https://blog.csdn.net/grd_java/article/details/121925792
本项目源码,码云:https://gitee.com/yin_zhipeng/vue-backstage-scaffolding.git
后台管理系统
,一般都是内部人员使用,所以对界面要求不高,一般都使用模板开发
。而前台系统
,是给游客使用,要凸显个性,所以一般自己开发,不使用模板
- 如果你
GitHub进不去
,可以到这里下载(码云)
:https://gitee.com/panjiachen/vue-admin-template.git
下载完成后,我们用它来当做项目,执行npm install --save 来下载相关依赖,然后通过npm run dev启动项目,最后浏览器查看项目
项目最终成果展示@TODO
一、概念和技术总结(重点,一定要搞懂)
这里总结项目中用到的前端知识,后面将不再赘述
1. vue
组件通信的方式(最基础的6种)
- 自定义事件:适用于子组件给父组件传递数据, $ on、和$ emit
- 全局事件总线$bus:适用于任何场景,Vue.prototype. $bus = this;
- pubsub-js发布和订阅:适用于任何场景,但是Vue用的不多,一般React框架经常使用
- Vuex:适用于任何场景,用的非常多
- solt插槽:使用于针对结构(标签)的父子组件通信,常用的有默认插槽,具名插槽和作用域插槽
2. vue-admin-template模板文件解析
文件目录解析(注意:以下所有文件夹和文件,你自己写效果也一样,并不是必须在这个模板文件中才能用)
build
--index.js webpack配置文件[我们基本不用修改]
mock
--mock数据文件夹[模拟一些假数据,mock.js实现],我们已经有后端和接口,基本不需要它
node_modules
--项目依赖的模块
p ublic
--存放ico图标,静态页面等静态资源,webpack打包时,不会编译此文件夹,原封不动打包到dist文件夹
src --我们写代码的地方
--api文件夹:异步请求相关代码
--assets文件夹:静态资源,一般是共享的,但是这里的静态资源,webpack打包是会编译
--components文件夹:全局组件(非路由组件)
--icons文件夹:svg矢量图
--layout文件夹:放置一些组件和混入mixin
--router文件夹:与路由相关的
--store文件夹:vuex相关的
--style文件夹:样式相关的
--utils文件夹:工具类,其中request.js是axios的二次封装,比较常用
--views文件夹:路由组件(不是全局组件)
App.vue
--根组件
main.js
--入口文件
permission.js
--导航守卫,主要控制登录等相关事务
settings
--对于项目的配置项(面向展示层),比如我们浏览器标签title显示什么,表头是否固定,导航栏logo是否显示
--剩下都是配置文件
.editorconfig
--编程风格配置,比如缩进统一2个空格
-- 很重要的3个配置文件,可以通过webpack对外暴露的函数process获取
.env.development
-- 开发环境的配置文件
.env.production
-- 上线环境的配置文件
.env.staging
-- 测试环境的配置文件
-- 重要但又不重要的3个配置文件
.eslintignore
-- eslint检测的忽略文件,对于这些文件它会忽略,和我们没关系,我们压根不用eslint检测
.eslintrc.js
-- eslint配置文件
.gitignore
-- 只和作者有关系,上传git的忽略文件
-- 不常用的配置文件
.travis.yml
-- 一些语言,开发版本的配置文件
babel.config.js
-- babel的配置文件,常用于配置按需加载,比如element ui 按需加载
jest.config.js
-- 测试框架的配置文件
LICENSE
-- 版权声明的文件
-- 重点配置文件
jsconfig.json
-- 配置src别名的文件
package.json
-- 配置项目信息,运行参数,需要的依赖
postcss.config.js
-- css配置文件,不同浏览器的兼容问题,可以在这里解决
vue.config.js
-- 可以当成webpack.config.js,做代理等操作,我们经常使用这个文件
router文件夹index.js解析
jsconfig.json文件配置src别名为@解析
3个环境配置文件,可以通过webpack对外暴露的函数process获取,注意配置文件中内容,要以VUE_APP_*****开头(就和,java类名首字母要大写一样,大家要共同遵守)
console.log(process)
console.log(process.env)
utils中auth.js文件详解
store文件夹详解
//lambda一个参数的表示形式, 我们传递的参数就是a,箭头后面是执行逻辑
a => return a;
3. 异步相关,前后端交互
1. 当年PanJiaChen开发此模板时,还没有async函数(ES6的语法),所以使用传统Promise处理异步,我们后面统一将其改造为使用async函数,对于Promise和async请参考文章:https://blog.csdn.net/grd_java/article/details/105384601
2. request.js文件
4. 导航守卫
不知道的参考官方文档https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
permission.js文件解析
5. 路由解析
记住一句话,所有路由都在找< router-view> ,所有子路由,都在找父路由组件中的< router-view>
整个路由进入首页后,为Layout组件,此组件分为3部分,sidebar导航栏,navbar顶部菜单栏,app-main内部二级路由,我们实际编写页面的地方
二、单点登录实现
登录页面直接使用模板提供的即可,我们对其样式进行一些修改,以让你知道如何对其自定义
1. 后端接口和响应结果分析
2. 解决跨域,以及请求头.几乎所有项目都需要的配置,背下来吧。
1. 首先,我们知道环境配置文件中,有VUE_APP_BASE_API这个东西,我们通过这个来规定请求路径,我们可以规定它.改完记得重启项目(我们是开发环境,所以修改.env.development文件)
2. 然后我们通过修改webpack的配置文件vue.config.js,配置跨域代理,主要位置,别写错位置,同样,配置完记得重启项目
//配置代理跨域
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8001`, //修改后台接口地址
// changeOrigin: true,
pathRewrite: {
['^'+process.env.VUE_APP_BASE_API]: ''
}
}
},
3. token请求头这种东西,直接配置到请求拦截器中就好了,request.js,注意token请求头的key必须为authorization(因为这是我们后端规定的,不是这个,后端没法正常解析)
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['authorization'] = getToken()
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
3. 验证码展示
后端直接返回一张图片给我们,我们可以通过window.URL.createObjectURL(response)来获取图片的一个url地址
window.URL.createObjectURL用于创建一个新的对象URL,该对象URL可以代表某一个指定的File对象或Blob对象
效果如下
1. 首先,我们后端的验证码功能没有响应码,而我们使用的模板,在request.js中封装了请求拦截器和响应拦截器,致命的是,响应拦截器直接拦截所有响应码不是20000的响应
2. 封装api请求,注意一定要将响应类型设置为’blob’(responseType:‘blob’)
export function captcha() {
return request({
url: 'captcha',
method: 'get',
responseType:'blob'
})
}
3. login页面,login/index.js文件引入api,然后展示验证码
//异步获取验证码
async getImgCode () {
await captcha().then(response => {
this.codesrc = window.URL.createObjectURL(response)
})
},
//html标签
<el-form-item prop="code" class="code">
<span class="svg-container">
<!-- <svg-icon icon-class="el-icon-s-flag" />-->
<i class="el-icon-edit"></i>
</span>
<el-input
class="code-input"
ref="code"
type="text"
v-model="loginForm.code"
placeholder="验证码"
name="code"
tabindex="2"
auto-complete="on"
@keyup.enter.native="handleLogin"
/>
</el-form-item>
<img :src="codesrc" class="code-img" @click="getImgCode">
//sass样式
.code{
width: 70%;
float: left;
}
.code-img{
float: right;
width: 29.6%;
//height: 100%;
}
4. 单点登录,退出登录,根据后端API实现
效果如下
1. api接口
api文件夹user.js文件,修改login,getInfo和logout三个接口
2. 路由组件编写登录函数逻辑
我们发现,此模板所有登录逻辑都在view/login/index.vue文件中的handleLogin方法中,对其进行修改
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {//发生表单验证后
this.loading = true//登录按钮可用
//调用action监听,user.js下面的login
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ path: this.redirect || '/' })//成功跳转路由,触发permission.js导航守卫
this.loading = false//异步过程中,阻止登录按钮的使用
}).catch(() => {
this.loading = false//异步过程中,依然阻止登录按钮使用
this.getImgCode()//登录失败,刷新验证码
})
} else {
console.log('error submit!!')
this.getImgCode()//刷新验证码
return false
}
})
}
3. 修改store(vuex)异步逻辑
所有操作都在store/user.js中,我们需要修改login和getInfo以及logout
// user login
//处理登录业务
async login({ commit },userInfo) {
//解构出用户名和密码
const { username,password,code} = userInfo;
//异步调用/api/user文件下的login
let result = await login({username: username.trim(),password:password,code:code});
if (result.code==20000){
//我们规定token为tokenHead + " " + token字符串
const token = result.data.tokenHead+' '+result.data.token;
//设置到state
commit("SET_TOKEN",token);
//通过auth.js文件的函数,设置到cookie
setToken(token)
}else{
//登录失败
return Promise.reject(new Error(result.message));
}
},
// get user info
async getInfo({ commit, state }) {
//异步调用/api/user文件下的login
let result = await getInfo(state.token);
if(result.code === 20000){
const { loginInfo } = result.data
if (!loginInfo) {
return reject('验证失败,请重新登录.');
}
const {username} = loginInfo;
commit('SET_NAME',username);
commit('SET_AVATAR','https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif')
}else{
//登录失败
return Promise.reject(new Error(result.message));
}
},
// user logout
async logout({ commit, state }) {
let result = await logout(state.token);
if(result.code === 20000){
removeToken() // must remove token first
resetRouter()
commit('RESET_STATE')
}else{
//退出登录失败
return Promise.reject(new Error(result.message));
}
},
5. 流程总结
三、后台管理系统实现
由于篇幅原因,我将其放在另一篇文章中:@TODO 还没写完