1. 路由配置
router文件夹下,index.js 配置
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home, meta: { requireAuth: true }, children: [ // 学生数据 { path: '/home/studentData', name: 'studentData', meta: { requireAuth: true }, component: () => import('../views/studentData/studentData.vue') }, // 老师数据 { path: '/home/teacherData', name: 'teacherData', meta: { requireAuth: true }, component: () => import('../views/teacherData/teacherData.vue') }, ] }, { path: '/login', name: 'login', component: () => import('../views/login/login.vue'), // 子路由 children: [ ] } ] // 多次点击同一个导航时会报错,所以添加了这段代码 const originalPush = VueRouter.prototype.push VueRouter.prototype.push = function push(location, onResolve, onReject) { if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject) return originalPush.call(this, location).catch(err => err) } const router = new VueRouter({ routes }) // 别的地方会用到 router,所以将它导出去 export default router
- 说明:因为此类项目只有中间表格部分会切换,所以路由配置采用的是:父子路由模式
- 一个父路由:home.vue,包含:1. 左侧导航,2. 头部信息栏,3.表格部分的容器
- view文件目录配置如下:(如果你不太熟练,先跟着我的配置走)
2. 登录页配置
login.vue(当前是纯静态页面,稍后添加接口与方法)
<template> <div class="login-box"> <div class="form-con"> <h2>Vue+element ui 管理系统实战</h2> <div class="label"> <el-input placeholder="请输入账号" v-model="userName"> <template slot="prepend"><i class="el-icon-user"></i></template> </el-input> </div> <div class="label"> <el-input placeholder="请输入密码" v-model="password" show-password @keyup.enter.native="loginFn()"> <template slot="prepend"><i class="el-icon-lock"></i></template> </el-input> </div> <div class="label"> <el-button class="login-btn" type="primary" @click="loginFn()" >登 录</el-button > </div> </div> </div> </template> <script> export default { name: "login", data() { return { userName: "", password: "", verify: "", }; }, }; </script> <style lang="scss" scope> .login-box { width: 100%; height: 100%; display: flex; text-align: center; background: url("~@/assets/4.jpg") no-repeat; background-size: 100% 100%; .form-con { h2 { color: #ffffff; // color: $colorRed; } width: 360px; height: 420px; margin: 150px auto auto auto; .label { margin: 40px 0; .login-btn { width: 100%; } } } } </style>
3. API层配置(接口配置)
- 接口采用分层设计,为了方便维护,会有以下四个基础文件(这些是推荐必须要有的,其余有需求可以自己加)
- 其中前三个文件写完之后,基本不用去动,一劳永逸,爽的不行
思路:深度解耦与高度复用
3.1 service.js 配置
此文件负责和后台打交道,统一处理所有接口(各种拦截处理、状态处理等)
import axios from 'axios' import vue from '../main.js' // 从本地获取token function getTokenByLocal() { let token = sessionStorage.getItem('token'); return token; } const service = axios.create({ baseURL: '/sys', // withCredentials: true, timeout: 5000, }) // 请求拦截 service.interceptors.request.use( config => { if (getTokenByLocal()) { // 在此可以设置所有接口headers头部 config.headers['token'] = getTokenByLocal(); }else{ // window.location.href="/login"; } return config }, error => { return Promise.reject(error) } ) // 响应拦截 service.interceptors.response.use( response => { let res = response.data; // console.log(res); // 状态码处理 if (res.code == '200') { // location.href = "home/login"; } // 如果为 -101 代表用户未登录 if(res.code == '-101'){ vue.$router.push('/login'); } return Promise.resolve(res); }, error => { return Promise.reject(error) } ) export default service;
3.2 common.js 配置
- 此文件只做一件事情:统一处理项目中所有接口的传参处理
- 一般来说,不会有太多花里胡哨的传参
// 将service.js引入进来 import service from './service.js' // post请求 80% 耦合度低 复用性高 export function requestOfPost(url, data){ return service.post(url, data); }
3.3 api.js 配置
- 此文件为二次封装,加入处理异步的 promise
import {requestOfPost} from './common.js' export function postRequest(url, data){ return new Promise((resolve, reject) => { requestOfPost(url, data).then(res => resolve(res)) .catch(error => reject(error)) }) }
3.4 url.j配置
- 此文件统一管理所有接口路径,不然项目里东一个西一个维护起来麻烦(架构师说的,咱也不敢反驳,仔细寻思了一下,这也是对的)
- 如果项目里的接口超过了一百个,可以拆分成两个
- 切记,加注释啊亲
const url = { // 登录 login: '/login', // 学生列表 getClassmates: '/getClassmates' } export default url;
4. 跨域处理
- 一般来说,本地开发都需要配置接口跨域,后台一般懒得处理(卑微前端的无力)
- 项目最外层添加文件: vue.config.js(这个文件只能这么命名,别的名字cli 服务不会识别)
- 配置如下
module.exports = { devServer: { compress: false, open: true, proxy: { '/sys': { // 代理地址 target: 'http://api.gebilaowang.com', // websocket (一般用于即时通讯,游戏,这里不需要,所以不开) ws: false, // 是否允许跨域 changeOrigin: true, // 重写 pathRewite: { '/sys': '/' } } } } }