需要使用的技术栈:脚手架、vuex、router以及element-ui和axios
目录
不会安装的可以看一下之前的安装教学demo1需要安装的技术栈
先看实现效果:
获取数据的话可以找我要一下本地数据的接口,如果想自己用mokejs模拟数据的话也可以 。不会模拟的话可以参考这篇mokejs模拟数据
接下来正式写demo
先写登录页面样式
Login.vue页面
<template> <div class="home"> <div class="homebox" v-loading="loading"> <h3>KGC后台管理系统</h3> <el-input class="input" v-model="username" style="width: 500px" placeholder="用户名" ></el-input> <el-input class="input" placeholder="密码" style="width: 500px" v-model="password" show-password ></el-input> <el-button type="primary" size="medium " @click="login" style="width: 500px" >登陆</el-button > </div> </div> </template> <script> export default { name: "Login", data() { return { username: "admin", password: 123, loading: false, }; }, methods: { login() { }, }, }; </script> <style> body { background-color: rgb(238, 243, 250); } .homebox { text-align: center; position: absolute; top: 50%; left: 50%; margin-top: -150px; margin-left: -300px; width: 600px; height: 300px; background-color: rgb(255, 255, 255); } h3 { padding-top: 20px; } .input { margin-bottom: 20px; } </style>
之后可以先写后台系统页面
<template> <div class="admin"> <div class="header"> <router-view name="Header"></router-view> </div> <router-view></router-view> <el-tabs v-model="activeName" :tab-position="tabPosition" type="card" @tab-click="handleClick" > <el-tab-pane label="用户管理" name="first"> <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="用户名"> </el-table-column> <el-table-column prop="role" label="角色"> </el-table-column> <el-table-column prop="phone" label="手机号码"> </el-table-column> <el-table-column prop="email" label="邮箱"> </el-table-column> <el-table-column label="操作"> <template v-slot="scope"> <el-button size="mini" type="danger" @click="deleteData(scope.$index, tableData)" >删除</el-button > </template> </el-table-column> </el-table> </template> </el-tab-pane> <!-- {{banner[0].id}} --> <el-tab-pane label="商品管理" name="second"> <template> <el-table :data="table" style="width: 80%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="商品名称"> </el-table-column> <el-table-column prop="price" label="单价"> </el-table-column> <el-table-column prop="number" label="库存"> </el-table-column> </el-table> </template> </el-tab-pane> </el-tabs> </div> </template> <script> // import axios from "axios"; import { mapState } from "vuex"; export default { name: "Admin", computed: { ...mapState(["tableData"]), ...mapState(["table"]), }, components: { Header: "Header", }, data() { return { tabPosition: "left", activeName: "first", }; }, methods: { handleClick(tab, event) { console.log(tab, event); }, }, }; </script> <style scoped> * { margin: 0; padding: 0; } .header { width: 100%; background-color: #00bfff; } </style>
头部样式:
<template> <div class="header"> <div class="header-left"> <div class="left">KGC后台管理系统</div> </div> <div class="header-right"> <div class="header-right__logout"> <el-button type="danger" size="20" @click="logout">退出</el-button> </div> <div class="header-right__info"> <div class="right">{{ user.name }}</div> </div> </div> </div> </template> <script> import { mapState } from "vuex"; export default { name: "Header", data() { return {}; }, mounted() {}, methods: { logout() { this.$confirm("您确定要退出吗, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { window.sessionStorage.removeItem("LeftList"); this.$message({ message: "你已经退出登陆!请重新登录账号", type: "warning", }); this.$router.push({ path: "/login" }); }) .catch((err) => err); }, }, computed: { ...mapState(["user"]), }, }; </script> <style scoped> .header { height: 50px; line-height: 50px; background-color: rgb(73, 80, 96); padding: 0 50px; color: #fff; box-shadow: 5px -2px 5px #00bfff; } .left { color: #fff; float: left; } .header-right__info { float: right; margin: 0 20px; } .header-right__logout { float: right; } </style>
把normal.css在app.vue 中或者在main中引入即可
接下来就可以现在这个页面中尝试获取数据
使用JSON-data数据
安装:npm install -g json-server
使用vuex获取数据
mounted() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); }); },
用同样的方法引入商品管理
这里想直接在点击登录页面后进入此网页
就在登录按钮中获取数据
login() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); }) },
当我们点击登陆时会看到获取到的数据
这时可以设置一个延迟两秒钟的定时器用来加载页面,加载完毕后结束
login() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); // 开启加载动画 this.loading = true; setTimeout(() => { this.loading = false; this.$message({ message: "恭喜你登陆成功,欢迎来到User页面", type: "success", }); }, 2000); }); },
效果如下:
通过循环开始遍历数据中存在的账号以及密码
login() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); // 开启加载动画 this.loading = true; setTimeout(() => { // 遍历账号以及密码 for (let i = 0; i < home.length; i++) { console.log(home[i].name); console.log(home[i].pwd); } this.loading = false; this.$message({ message: "恭喜你登陆成功,欢迎来到User页面", type: "success", }); }, 2000); }); },
效果如下:
因为密码都是123所以这里就不获取他的密码了,直接判断他为123
if (this.username == home[i].name && this.password == 123) { // 如果为真,那么就让登陆通过 this.loading = false; this.$message({ message: "恭喜你登陆成功,欢迎来到User页面", type: "success", }); }
再次判断如果账号为超级管理员,那么就进入超级管理员页面,如果账号密码不是超级管理员,就进入普通的用户页面,否则不允许进入页面
User页面如下:
<template> <div class="admin"> <div class="header"> <router-view name="Header"></router-view> </div> <router-view></router-view> <el-tabs v-model="activeName" :tab-position="tabPosition" type="card" @tab-click="handleClick" > <!-- {{banner[0].id}} --> <el-tab-pane v-if="show" label="商品管理" name="first"> <template> <el-table :data="table" style="width: 90%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="商品名称"> </el-table-column> <el-table-column prop="price" label="单价"> </el-table-column> <el-table-column prop="number" label="库存"> </el-table-column> </el-table> </template> </el-tab-pane> </el-tabs> </div> </template> <script> // import axios from "axios"; import { mapState } from "vuex"; export default { name: "Admin", computed: { ...mapState(["table"]), }, components: { Header: "Header", }, data() { return { tabPosition: "left", activeName: "first", content: "", banner: "", body: "", show: true, }; }, mounted() { this.$axios.get("/goods").then((resf) => { const user = resf.data; console.log(user); this.$store.commit("record", user); for (let i = 0; i < user.length; i++) {} }); }, methods: { handleClick(tab, event) { console.log(tab, event); }, }, }; </script> <style scoped> * { margin: 0; padding: 0; } .header { width: 100%; background-color: #00bfff; } </style>
在router里写入以下代码:(加入一个守卫导航防止跳转)
router.beforeEach((to, from, next) => { if (to.path == '/login') { next() } else { let token = window.sessionStorage.getItem('name') if (!token) { next('/login') } else { next() } } }) const originalPush = VueRouter.prototype.push // 重写了原型上的push方法,统一的处理了错误信息 VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) }
下面为源代码:
components/Header.vue
<template> <div class="header"> <div class="header-left"> <div class="left">KGC后台管理系统</div> </div> <div class="header-right"> <div class="header-right__logout"> <el-button type="danger" size="20" @click="logout">退出</el-button> </div> <div class="header-right__info"> <!-- <div class="right">{{ user.name }}</div> --> </div> </div> </div> </template> <script> import { mapState } from "vuex"; export default { name: "Header", data() { return {}; }, mounted() {}, methods: { logout() { this.$confirm("您确定要退出吗, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { window.sessionStorage.removeItem("LeftList"); this.$message({ message: "你已经退出登陆!请重新登录账号", type: "warning", }); this.$router.push({ path: "/login" }); }) .catch((err) => err); }, }, computed: { ...mapState(["user"]), }, }; </script> <style scoped> .header { height: 50px; line-height: 50px; background-color: rgb(73, 80, 96); padding: 0 50px; color: #fff; } .left { color: #fff; float: left; } .header-right__info { float: right; margin: 0 20px; } .header-right__logout { float: right; } </style>
plugins/axios.js
"use strict"; import Vue from 'vue'; import axios from "axios"; let config = { baseURL:' http://localhost:3000' }; const _axios = axios.create(config); _axios.interceptors.request.use( function(config) { return config; }, function(error) { return Promise.reject(error); } ); _axios.interceptors.response.use( function(response) { return response; }, function(error) { return Promise.reject(error); } ); Plugin.install = function(Vue, options) { Vue.axios = _axios; window.axios = _axios; Object.defineProperties(Vue.prototype, { axios: { get() { return _axios; } }, $axios: { get() { return _axios; } }, }); }; Vue.use(Plugin) export default Plugin;
router/index.js
import Vue from 'vue' import VueRouter from 'vue-router' import Admin from '../views/Admin.vue' import User from '../views/User.vue' import Header from '@/components/Header'; import Home from '../views/Home.vue' Vue.use(VueRouter) const routes = [ { path:'/', name:'Home', component:Home }, { path: '*', redirect: '/login' }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hazsh].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') }, { path: '/login', name: 'Login', // route level code-splitting // this generates a separate chunk (about.[hazsh].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') }, { path: '/user', name: 'User', // route level code-splitting // this generates a separate chunk (about.[hazsh].js) for this route // which is lazy-loaded when the route is visited. components: { default: User, Header: Header } }, { path: '/admin', name: 'Admin', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. components: { default: Admin, Header: Header } } ] const router = new VueRouter({ routes, mode:'history' }) router.beforeEach((to, from, next) => { if (to.path == '/login') { next() } else { let token = window.sessionStorage.getItem('name') if (!token) { next('/login') } else { next() } } }) const originalPush = VueRouter.prototype.push // 重写了原型上的push方法,统一的处理了错误信息 VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) } export default router
store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { tableData:JSON.parse(window.sessionStorage.getItem('rightsList')||'{}'), table:[], user:JSON.parse(window.sessionStorage.getItem('liftList')||'{}') }, mutations: { addrecord(state,preload){ // console.log(preload) state.tableData=preload console.log(state.tableData); window.sessionStorage.setItem('rightsList',JSON.stringify(preload)) }, record(state,preload){ state.table = preload console.log(state.table); // window.sessionStorage.setItem('List',JSON.stringify(preload)) }, setUser(state,preload) { state.user = preload console.log(state.user); window.sessionStorage.setItem('liftList',JSON.stringify(preload)) } }, actions: { }, modules: { } })
views/Admin.vue
<template> <div class="admin"> <div class="header"> <router-view name="Header"></router-view> </div> <router-view></router-view> <el-tabs v-model="activeName" :tab-position="tabPosition" type="card" @tab-click="handleClick" > <el-tab-pane label="用户管理" name="first"> <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="用户名"> </el-table-column> <el-table-column prop="role" label="角色"> </el-table-column> <el-table-column prop="phone" label="手机号码"> </el-table-column> <el-table-column prop="email" label="邮箱"> </el-table-column> <el-table-column label="操作"> <template v-slot="scope"> <el-button size="mini" type="danger" @click="deleteData(scope.$index,tableData)" >删除</el-button > </template> </el-table-column> </el-table> </template> </el-tab-pane> <!-- {{banner[0].id}} --> <el-tab-pane v-if="show" label="商品管理" name="second"> <template> <el-table :data="table" style="width: 80%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="商品名称"> </el-table-column> <el-table-column prop="price" label="单价"> </el-table-column> <el-table-column prop="number" label="库存"> </el-table-column> </el-table> </template> </el-tab-pane> </el-tabs> </div> </template> <script> // import axios from "axios"; import { mapState } from "vuex"; export default { name: "Admin", computed: { ...mapState(["tableData"]), ...mapState(["table"]), }, components: { Header: "Header", }, data() { return { tabPosition: "left", activeName: "first", content: "", banner: "", body: "", show: true, }; }, mounted() { this.$axios.get("/users").then((res) => { console.log(res); this.banner = res.data; console.log(this.banner); // const index = data.list.findIndex(item=>item.id === body.id); // console.log(index); }); this.$axios.get("/goods").then((resf) => { const user = resf.data; console.log(user); this.$store.commit("record", user); for (let i = 0; i < user.length; i++) {} }); // this.$axios.get("/goods").then((good)=>{ // console.log(good); // this.goods = good.data, // const user = resf.data; // console.log(user); // this.$store.commit("record", user); // // window.sessionStorage.setItem('List',JSON.stringify(good)) // }) /* this.$axios.delete("/api/users/" + user.id).then((rest) => { console.log(rest); }); */ }, methods: { /* deleteData(index,row){ this.tableData.splice(index, 1) console.log("进行了删除操作") console.log("index的值是:"+index) console.log("row的值是:",row) }, */ getUserList(){ this.$axios.get("/users").then((res) => { console.log(res); this.banner = res.data; console.log(this.banner); // const index = data.list.findIndex(item=>item.id === body.id); // console.log(index); }); }, handleClick(tab, event) { console.log(tab, event); }, // 删除 deleteData(index,row) { this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", }) .then(() => { this.$message({ type: "success", message: "删除成功!", }); this.tableData.splice(index, 1) }) .catch(() => { this.$message({ type: "info", message: "已取消删除", }); }); // console.log(index, row); // 传一个参数id post就直接传 // 解构写法 // const {data,res} = await('/api/get/user',{ id }) // 如果是get请求 /* const {data,res} = await('/api/get/user',{ params:{ // id:id id } }) */ }, }, }; </script> <style scoped> * { margin: 0; padding: 0; } .header { width: 100%; background-color: #00bfff; } </style>
views/Home.vue
<template> <div class="home"> <div class="homebox" v-loading="loading"> <h3>KGC后台管理系统</h3> <el-input class="input" v-model="username" style="width: 500px" placeholder="用户名" ></el-input> <el-input class="input" placeholder="密码" style="width: 500px" v-model="password" show-password ></el-input> <el-button type="primary" size="medium " @click="login" style="width: 500px" >登陆</el-button > </div> </div> </template> <script> // @ is an alias to /src export default { name: "Home", data() { return { username: "", password: 123, loading: false, }; }, methods: { login() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); this.loading = true; var timer = setTimeout(() => { this.loading = false; for (let i = 0; i < home.length; i++) { console.log(home[i].name); if (this.username == home[i].name && this.password == 123) { this.loading = false; this.$message({ message: "恭喜你,登陆成功!", type: "success", }); return this.$router.push("/admin"); } } for (let j = 0; j < home.length; j++) { console.log(home[j].name); if (this.username != home[j].name || this.password != 123) { this.$message.error("错了哦,这是一条错误消息"); return this.$router.push("/home"); } } }, 2000); console.log(res); }); this.$axios.get("/goods").then((resf) => { const user = resf.data; console.log(user); this.$store.commit("record", user); for (let i = 0; i < user.length; i++) {} }); }, }, }; </script> <style> body { background-color: rgb(238, 243, 250); } .homebox { text-align: center; position: absolute; top: 50%; left: 50%; margin-top: -150px; margin-left: -300px; width: 600px; height: 300px; background-color: rgb(255, 255, 255); } h3 { padding-top: 20px; } .input { margin-bottom: 20px; } </style>
views/Login.vue
<template> <div class="home"> <div class="homebox" v-loading="loading"> <h3>KGC后台管理系统</h3> <el-input class="input" v-model="username" style="width: 500px" placeholder="用户名" ></el-input> <el-input class="input" placeholder="密码" style="width: 500px" v-model="password" show-password ></el-input> <el-button type="primary" size="medium " @click="login" style="width: 500px" >登陆</el-button > </div> </div> </template> <script> // @ is an alias to /src export default { name: "Login", data() { return { username: "admin", password: 123, loading: false, }; }, methods: { login() { this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); console.log(home); this.loading = true; setTimeout(() => { for (let i = 0; i < home.length; i++) { console.log(home[i].name); if (this.username == home[i].name && this.password == 123) { if (this.username != 'admin' && this.password ==123) { this.loading = false; this.$message({ message: "恭喜你登陆成功,欢迎来到User页面", type: "success", }); this.loading = false; this.$store.commit("setUser", res.data[i]); window.sessionStorage.setItem("name", res.data.name); return this.$router.push("/user"); }else{ this.loading = false; this.$message({ message: "Hello,Welcome to the admin page!", type: "success", }); this.loading = false; this.$store.commit("setUser", res.data[i]); window.sessionStorage.setItem("name", res.data.name); return this.$router.push("/admin"); } } } for (let j = 0; j < home.length; j++) { this.loading = false; console.log(home[j].name); if (this.username != home[j].name || this.password != 123) { this.$message.error( "错了哦,可能是你的账号密码有问题,请重新填写" ); return this.$router.push("/home"); } } console.log(res); }, 2000); }); this.$axios.get("/goods").then((resf) => { const user = resf.data; console.log(user); this.$store.commit("record", user); for (let i = 0; i < user.length; i++) {} }); }, }, }; </script> <style> body { background-color: rgb(238, 243, 250); } .homebox { text-align: center; position: absolute; top: 50%; left: 50%; margin-top: -150px; margin-left: -300px; width: 600px; height: 300px; background-color: rgb(255, 255, 255); } h3 { padding-top: 20px; } .input { margin-bottom: 20px; } </style>
views/User.vue
<template> <div class="admin"> <div class="header"> <router-view name="Header"></router-view> </div> <router-view></router-view> <el-tabs v-model="activeName" :tab-position="tabPosition" type="card" @tab-click="handleClick" > <!-- {{banner[0].id}} --> <el-tab-pane v-if="show" label="商品管理" name="first"> <template> <el-table :data="table" style="width: 90%"> <el-table-column prop="id" label="编号"> </el-table-column> <el-table-column prop="name" label="商品名称"> </el-table-column> <el-table-column prop="price" label="单价"> </el-table-column> <el-table-column prop="number" label="库存"> </el-table-column> </el-table> </template> </el-tab-pane> </el-tabs> </div> </template> <script> // import axios from "axios"; import { mapState } from "vuex"; export default { name: "Admin", computed: { ...mapState(["table"]), }, components: { Header: "Header", }, data() { return { tabPosition: "left", activeName: "first", content: "", banner: "", body: "", show: true, }; }, mounted() { this.$axios.get("/goods").then((resf) => { const user = resf.data; console.log(user); this.$store.commit("record", user); for (let i = 0; i < user.length; i++) {} }); }, methods: { handleClick(tab, event) { console.log(tab, event); }, }, }; </script> <style scoped> * { margin: 0; padding: 0; } .header { width: 100%; background-color: #00bfff; } </style>
App.vue
<template> <div id="app"> <div class="header"> <router-view name="Header"></router-view> </div> <router-view></router-view> </div> </template> <script> export default { name: "app", }; </script> <style> </style>
main.js
import Vue from 'vue' import './plugins/axios' import App from './App.vue' import router from './router' import store from './store' import './plugins/element.js' import './assets/css/normalize.css' Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
这里的删除数据是假删除,防止真实删除本地数据。
实现效果:
验证账号是否存在
这里更新一条更方便的验证登录的代码
login() { this.$axios.get("/users").then((v) => { this.loading = true; const uname = []; const passw = []; console.log(v); const res = v.data; for (var i = 0; i < res.length; i++) { uname.push(res[i].name); passw.push(res[i].pwd); } console.log(uname); console.log(passw); console.log(uname.indexOf(this.username) === -1); setTimeout(() => { if (uname.indexOf(this.username) === -1) { this.loading = false; this.$message.error("账号不存在,请重新输入!"); } else { var index = uname.indexOf(this.username); console.log(passw[index]); if (passw[index] == this.password) { this.loading = false; this.$message({ message: "恭喜你,登陆成功!", type: "success", }); this.$router.push("./Page"); } else { this.loading = false; this.$message.error("密码错误,请重新输入"); } } }, 2000); }); },
这段代码可以将存在的数据用数组包裹起来,并将输入的账号和密码与数组里的账号相对比,判断他是否存在,不存在的话就会显示账号不存在,如果账号名与数据中的账号一致,就会去判断其密码是否与之对应,如果不对应就判断他为密码错误,如果都正确,那么则进入下一页