vueAdmin前端学习笔记
Posted 打怪兽升级
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vueAdmin前端学习笔记相关的知识,希望对你有一定的参考价值。
vueAdmin前端学习笔记
1.安装VUE项目
第一步:vue-ui
# 安装淘宝npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# vue-cli 安装依赖包
cnpm install --g vue-cli
# 打开vue的可视化管理工具界面
vue ui
第二步:创建
第三步:详情
第四步:选择手动
第五步:配置
第六步:点击创建项目
第七步:启动项目
第八步:vsCode启动项目
npm run serve
2.安装element-ui
npm install element-ui --save
然后我们打开项目src目录下的main.js,引入element-ui依赖。
import Element from 'element-ui'
import "element-ui/lib/theme-chalk/index.css"
Vue.use(Element)
这样我们就可以愉快得在官网上选择组件复制代码到我们项目中直接使用啦。
3.删除不必要的页面
3.1删除/viwes/Home.vue
3.2删除App.vue
4.安装axios、qs、mockjs
-
axios:一个基于 promise 的 HTTP 库,类ajax
-
qs:查询参数序列化和解析库
-
mockjs:为我们生成随机数据的工具库
4.1安装axios
npm install axios --save
# 然后同样我们在main.js中全局引入axios
import axios from 'axios'
Vue.prototype.$axios = axios //全局使用
4.2安装qs
npm install qs --save
4.3安装mockjs
npm install mockjs --save-dev
5.页面路由
5.1删除页面
5.2创建页面
1.创建Login.vue
<template>
<div>登录页面</div>
</template>
<script>
export default {
name: "Login"
}
</script>
<style scoped>
</style>
1.创建Home.vue
<template>
<div>测试主页 </div>
</template>
<script>
export default {
name: 'Home',
}
</script>
<style>
</style>
5.3页面router/index.js
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 方式一
component: Login //方式二
}
]
6.登录页面
6.1页面展示
6.2在src/App.vue调整全局样式
我们先调整一下全局的样式
将原页面的style便签删除,更换为一下的style便签内容,下面是调整后的整个页面
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
html, body, #app {
font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 'Microsoft Yahei', sans-serif;
height: 100%;
padding: 0;
margin: 0;
font-size: 15px;
}
</style>
6.3src/views/Login.vue
一下页面是写好后的页面,还未发请求前
<template>
<el-row style="height: 100%">
<el-col :xl="6" :lg="7">
<!-- 标题 -->
<h2>欢迎来到VueAdmin管理界面</h2>
<!-- 使用 el-image引入图片 -->
<el-image
:src="require('@/assets/微信图片_20210919105336.jpg')"
style="height: 180px; width: 180px"
></el-image>
<p>公众号:MarkerHup</p>
<p>扫描二维码,回复</p>
</el-col>
<el-col :span="1">
<!-- 分割线 -->
<el-divider direction="vertical"></el-divider>
</el-col>
<el-col :xl="6" :lg="7">
<!--
:model="loginForm" 绑定的表单
:rules="rules" 校验规则
ref="loginForm" 注册实例,可以通过 this.$refs[loginForm]获取
-->
<el-form
:model="loginForm"
:rules="rules"
ref="loginForm"
label-width="80px"
class="demo-loginForm"
>
<el-form-item label="用户名" prop="userName" style="width: 380px">
<el-input v-model="loginForm.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="passWord" style="width: 380px">
<el-input v-model="loginForm.passWord"></el-input>
</el-form-item>
<el-form-item label="验证码" prop="code" style="width: 380px">
<el-input
v-model="loginForm.code"
style="width: 170px; float: left"
></el-input>
<el-image src="" class="captchaImg"></el-image>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')"
>登录
</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<script>
export default {
name: "Login",
data() {
return {
// 表单
loginForm: {
userName: "",
passWord: "",
code: "",
},
// 校验
rules: {
userName: [
{required: true, message: "请输入用户名", trigger: "blur"},
{
min: 3,
max: 50,
message: "长度在 3 到 50 个字符",
trigger: "blur",
},
],
passWord: [
{required: true, message: "请输入密码", trigger: "change"},
],
code: [{required: true, message: "请输入验证码", trigger: "change"}],
},
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert("submit!");
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style scoped>
/**
* el-row 的设置
* background-color: #fafafa; 设置背景颜色
* height: 100%; 设置高度,覆盖所有的高度
* display: flex; 横向居中
* align-items: center; 上下居中
* text-align: center; 文字居中
*/
.el-row {
background-color: #fafafa;
height: 100%;
display: flex;
align-items: center;
text-align: center;
justify-content: center;
}
/*.el-row {*/
/* height: 100%;*/
/* background-color: #fafafa; !*设置背景颜色*!*/
/* display: flex;*/
/* justify-content: center;*/
/* align-items: center;*/
/* text-align: center;*/
/*}*/
/* 分割线的高度 */
.el-divider {
height: 200px;
}
.captchaImg {
/*靠左边*/
float: left;
/*验证码偏移8px*/
margin-left: 8px;
/*圆角*/
border-radius: 4px;
}
</style>
6.4获取验证码
现在没有后端,用mockjs模拟生成验证码
6.4.1安装mockjs
npm install mockjs --save-dev
6.4.2创建mock.js
// 引入mockjsconst
const Mock = require('mockjs')
// 获取 mock.Random 对象
// 参考:https://github.com/nuysoft/Mock/wiki/Mock.Random
const Random = Mock.Random
let Result = {
code: 200,
msg: '操作成功',
data: null
}
Mock.mock('/captcha','get',()=>{
Result.data = {
UUID: Random.string(32), // 获取一个32位的随机字符串,
captchaImg: Random.dataImage('120x40','p7n5w') //生成验证码为11111的base64图片编码
}
return Result
})
6.4.3注册
// 在src/main,js
require("./mock.js")
6.4.4login页面(重要)
- 在methods添加请求验证码的方法
// 获取验证码
getCaptCha() {
this.$axios.get('/captcha').then(res => {
debugger;
this.loginForm.UUID = res.data.data.token;
this.captchaImg = res.data.data.captchaImg;
})
}
- 新增created在进入页面时加载
created() {
this.getCaptCha();
},
- 新增参数
1.在loginForm里添加UUID,
2.在data里面添加captchaImg,
3.验证码展示
<el-image :src="captchaImg" class="captchaImg"></el-image>
6.4.5页面展示
6.5登录
6.5.1使用mockjs模拟登录
在mock.js添加
Mock.mock('/login','post',()=>{ return Result})
6.5.2将token存到localStorage
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token;
localStorage.setItem("token", token)
}
},
actions: {},
modules: {}
})
6.5.3发送login请求
this.$axios.post('/login', this.loginForm).then(res => {
const jwt = res.headers['authorization'];
this.$store.commit("SET_TOKEN", jwt);
this.$router.push("/index");
})
6.5.4测试
7.定义全局axios拦截器
7.1在src/axios.js
import axios from "axios";import router from "@/router";import Element from "element-ui"axios.defaults.daseURL = "http://localhost:8081"const request = axios.create({ timeout: 5000, //超时时间 headers: { 'Content-Type': 'application/json; charset=utf-8' // 返回的JSON类型数据 }})// 请求的拦截,查看是否有tokenrequest.interceptors.request.use(config => { config.headers['Authorization'] = localStorage.getItem("token") // 请求头带上token return config})// 返回的结果request.interceptors.response.use(response => { let res = response.data; console.log("response") console.log(res) if (res.code === 200) { return response } else { Element.Message.error(res.msg ? res.msg : '系统异常!', {duration: 3 * 1000}) return Promise.reject(response.data.msg) }}, error => { // 异常的情况 console.log(error) if (error.response.data) { error.message = error.response.data.msg } // 401没有权限 if (error.response.status === 401) { router.push("/login") } Element.Message.error(error.message, {duration: 3 * 1000}) return Promise.reject(error)})export default request
7.2在main.js全局引入
7.3测试
1.在mock.js中的login方法添加错误信息
2.页面测试
8.index页面编写
8.1页面
在src/views/创建index.vue
<template>
<el-container>
<!-- 侧边栏-->
<el-aside width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i class="el-icon-s-home"></i> <span slot="title">首页</span></template>
</el-menu-item>
</router-link>
<el-submenu index="1">
<template slot="title"><i class="el-icon-s-operation"></i> <span>系统管理</span></template>
<el-menu-item index="1-1">
<template slot="title"><i class="el-icon-s-custom"></i> <span slot="title">用户管理</span></template>
</el-menu-item>
<el-menu-item index="1-2">
<template slot="title"><i class="el-icon-rank"></i> <span slot="title">角色管理</span></template>
</el-menu-item>
<el-menu-item index="1-3">
<template slot="title"><i class="el-icon-menu"></i> <span slot="title">菜单管理</span></template>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-s-tools"></i> <span>系统工具</span></template>
<el-menu-item index="2-2">
<template slot="title"><i class="el-icon-s-order"></i> <span slot="title">数字字典</span></template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!-- 头部信息-->
<el-header>
<strong>VueAdmin后台管理系统学习</strong>
<div class="header-avatar">
<!-- 头像-->
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<!-- 下拉框-->
<el-dropdown>
<span class="el-dropdown-link">
Admin<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- 最后面的文字跳转-->
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">网站</el-link>
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">学习</el-link>
</div>
</el-header>
<!-- 主体信息-->
<el-main>主体信息</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
name: 'Index',
}
</script>
<style>
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
text-align: center;
line-height: 160px;
}
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-menu-vertical-demo {
height: 100%;
}
</style>
8.2效果图
9.抽取代码
将index中的左侧导航栏代码和头部代码抽取为公共的
9.1抽取后的导航栏
在views新建inc/SideMenu
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i class="el-icon-s-home"></i> <span slot="title">首页</span></template>
</el-menu-item>
</router-link>
<el-submenu index="1">
<template slot="title"><i class="el-icon-s-operation"></i> <span>系统管理</span></template>
<el-menu-item index="1-1">
<template slot="title"><i class="el-icon-s-custom"></i> <span slot="title">用户管理</span></template>
</el-menu-item>
<el-menu-item index="1-2">
<template slot="title"><i class="el-icon-rank"></i> <span slot="title">角色管理</span></template>
</el-menu-item>
<el-menu-item index="1-3">
<template slot="title"><i class="el-icon-menu"></i> <span slot="title">菜单管理</span></template>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-s-tools"></i> <span>系统工具</span></template>
<el-menu-item index="2-2">
<template slot="title"><i class="el-icon-s-order"></i> <span slot="title">数字字典</span></template>
</el-menu-item>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
</style>
9.2抽取后的头部
<template>
<el-header>
<strong>VueAdmin后台管理系统学习</strong>
<div class="header-avatar">
<!-- 头像-->
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<!-- 下拉框-->
<el-dropdown>
<span class="el-dropdown-link">
Admin<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- 最后面的文字跳转-->
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">网站</el-link>
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">学习</el-link>
</div>
</el-header>
</template>
<script>
export default {
name: 'SideHeader',
}
</script>
<style>
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
</style>
9.3抽取后的Home
<!--<template>-->
<!-- <div>测试主页 </div>-->
<!--</template>-->
<!--<script> -->
<!--export default {-->
<!-- name: 'Home',-->
<!-- -->
<!--}-->
<!--</script>-->
<!--<style>-->
<!--</style>-->
<template>
<el-container>
<!-- 侧边栏-->
<el-aside width="200px">
<SideMenu></SideMenu>
</el-aside>
<el-container>
<!-- 头部信息-->
<el-header>
<SideHeader></SideHeader>
</el-header>
<!-- 主体信息-->
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
import SideHeader from "@/views/inc/SideHeader";
export default {
name: 'Home',
components: {SideMenu, SideHeader},
}
</script>
<style>
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
text-align: center;
line-height: 160px;
}
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
</style>
9.4抽取后的index
<template>
<div>测试主页 </div>
</template>
<script>
export default {
name: 'Index',
}
</script>
<style>
</style>
9.5抽取的router.js
将index路由放到children中
9.5抽取后的页面
10.创建页面
10.1在views新建system/User.vue
<template>
<div>用户测试</div>
</template>
<script>
export default {
name: 'User',
}
</script>
<style>
</style>
10.2在views新建system/Role.vue
<template>
<div>角色测试</div>
</template>
<script>
export default {
name: 'Role',
}
</script>
<style>
</style>
10.3在views新建system/Menuvue
<template>
<div>菜单测试</div>
</template>
<script>
export default {
name: 'Menu',
}
</script>
<style>
</style>
10.4在router.js添加
以下是代码router.js代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
import Index from '@/views/index'
import User from "@/views/system/User";
import Role from "@/views/system/Role";
import Menu from "@/views/system/Menu";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
children: [
{
path: '/index',
name: 'Index',
component: Index
},
{
path: '/users',
name: 'SysUser',
component: User
},
{
path: '/roles',
name: 'SysRole',
component: Role
},
{
path: '/menus',
name: 'SysMenu',
component: Menu
},
]
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 方式一
component: Login //方式二
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
10.4测试
分别访问:看页面的变化
http://localhost:8080/menus
http://localhost:8080/roles
http://localhost:8080/users
11.导航栏绑定页面
完成后点击页面测试看是否发生变化
<router-link to="/users">
</router-link>
12修改头像和用户名
在inc/SideHeader中修改头像和用户名从后端获取
13.个人中心
13.1在views/system/新建UserCenter.vue
<template>
<div style="text-align: center;"><h2>你好!{{ userInfo.username }} 同学</h2>
<el-form :model="passForm" status-icon :rules="rules" ref="passForm" label-width="100px">
<el-form-item label="旧密码" prop="currentPass">
<el-input type="password" v-model="passForm.currentPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="password">
<el-input type="password" v-model="passForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="passForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('passForm')">提交</el-button>
<el-button @click="resetForm('passForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "Login", data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.passForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
userInfo: {},
passForm: {password: '111111', checkPass: '111111', currentPass: '111111'},
rules: {
password: [{required: true, message: '请输入新密码', trigger: 'blur'}, {
min: 6,
max: 12,
message: '长度在 6 到 12 个字符',
trigger: 'blur'
}],
checkPass: [{required: true, validator: validatePass, trigger: 'blur'}],
currentPass: [{required: true, message: '请输入当前密码', trigger: 'blur'},]
}
}
}, created() {
this.getUserInfo()
}, methods: {
getUserInfo() {
this.$axios.get("/sys/userInfo").then(res => {
this.userInfo = res.data.data;
})
}, submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
const _this = this
this.$axios.post('/sys/user/updataPass', this.passForm).then(res => {
_this.$alert(res.data.msg, '提示', {
confirmButtonText: '确定', callback: action => {
this.$refs[formName].resetFields();
}
});
})
} else {
console.log('error submit!!');
return false;
}
});
}, resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
.el-form {
width: 420px;
margin: 50px auto;
}
</style>
13.2在router.js添加
{
path: '/userCenter',
name: 'UserCenter',
component: ()=>import("@/views/system/UserCenter")
},
13.3修改SideHeader.vue
删除所有页面的 line-height: 160px;
13.4测试页面
14退出
- 在SideHeader.vue给退出添加点击按钮
<!-- 在el-dropdown-item标签里, @click不可以用,要使用@click.native-->
<el-dropdown-item @click.native="logout">退出</el-dropdown-item>
- 在SideHeader.vue的methods编写点击退出方法
logout(){
this.$axios.post("/logout").then(res => {
localStorage.clear();
sessionStorage.clear();
this.$store.commit("resetState");
this.$router.push("/login")
})
},
- 在store/index.js添加删除的方法
- 在mock.js模拟退出请求
Mock.mock('/logout','post',()=>{ return Result})
- 测试
点击页面退出看效果
15将导航改为动态获取(可忽略)
可以忽略,直接过16
先用mock.js模拟从服务器返回数据
15.1主要修改
15.2修改后SideMenu.vue的页面
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i :class="el-icon-s-home"></i> <span slot="title">首页</span></template>
</el-menu-item>
</router-link>
<el-submenu :index=menu.name
v-for="menu in menuList">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.title }}</span>
</template>
<router-link :to="item.path" v-for="item in menu.children">
<el-menu-item :index="item.name">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
</el-menu-item>
</router-link>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
data() {
return {
menuList: [],
}
},
created() {
this.getMenuList();
},
methods: {
getMenuList() {
this.$axios.get("/sys/menuList").then(res => {
this.menuList = res.data.data;
})
}
}
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
.a {
text-decoration: none;
}
</style>
15.3mock.js
Mock.mock('/sys/menuList', 'get', () => {
Result.data = [
二.2vueadmin-template反向代理/路由配置,idc增查删