前言
入职一家新公司,报道第一天任务安排的是一个后台管理系统,项目交接给我之前,其他同事写过几个页面。这是一个船新的挑战,后台管理系统搞起。
项目搭建
npm install -g @vue/cli // 安装新版vue脚手架
vue --version // 检查vue版本
vue create your-project-name // 创建项目
这里我选择了,第一个vue2,babel与eslint。
项目配置
main.js
import Vue from 'vue'
import App from './App.vue'
import axios from '@/utils/request' // 封装axios
import router from '@/router' // 路由管理
import store from '@/store' // vuex状态管理
import lodash from 'lodash' // lodash(可用可不用的js方法库)
import ElementUI from 'element-ui' // 完整引入Element
import '../theme/index.css';
import '@/assets/css/common.less' // 公共方法
import './permission' // 权限路由控制
Vue.prototype.$axios = axios;
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.use(lodash)
new Vue({
el: '#app',
router,
store,
render: h => h(App),
}).$mount('#app')
utils/request.js(axios封装)
import axios from "axios";
import NProgress from "nprogress"; // 进度条
import "nprogress/nprogress.css" // 进度条样式
import { Message } from "element-ui";
import { hasToken, getToken } from "@/utils/common"
// import router from "./router"
console.log("当前环境变量:" + process.env.NODE_ENV);
console.log("当前环境路径:" + process.env.VUE_APP_URL);
const service = axios.create({
baseURL: process.env.VUE_APP_URL,
// timeout: 10000 // 超时时间
});
// 请求拦截器
service.interceptors.request.use(
config => {
NProgress.start();
if (hasToken()) {
config.headers["Authorization"] = getToken()
}
return config;
},
error => {
console.log(error);
return Promise.reject();
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
NProgress.done();
if (response.status === 200) {
return Promise.resolve(response.data);
} else {
Promise.reject(response.data);
}
},
error => {
NProgress.done();
// 请求超时
if (error.code === "ECONNABORTED" && error.message.indexOf("timeout") !== -1) {
Message.error({
message: "接口请求超时",
center: true,
showClose: true,
duration: 2000
});
}
let errorResponse = error.response;
if (errorResponse) {
switch (errorResponse.status) {
case 400:
Message.error({
message: errorResponse.data.message,
center: true,
showClose: true,
duration: 2000
});
break;
case 401:
Message.warning({
message: "暂无权限",
center: true,
showClose: true,
duration: 2000
});
return
case 500:
Message.warning({
message: "服务器异常",
center: true,
showClose: true,
duration: 2000
});
return
case 404:
Message.warning({
message: "资源未找到",
center: true,
showClose: true,
duration: 2000
});
return
}
}
return Promise.reject(errorResponse.data);
}
);
export default service;
utils/common.js(公共方法封装)
// 是否有token
export function hasToken() {
let token = localStorage.getItem("token");
if (token) return true
return false
}
// 获取token
export function getToken() {
return localStorage.getItem("token");
}
// 移除token
export function removeToken() {
return localStorage.removeItem("token");
}
vue.config.js
module.exports = {
publicPath:'./' ,
devServer: {
proxy: {
'/api':{ // 配置代理
target: 'http://192.168.3.20:8079',
changeOrigin: true,
pathRewrite: {
'^/api': '/api'
}
},
},
disableHostCheck: true
},
chainWebpack: config => {
// 其他配置
config.entry('main').add('babel-polyfill') // main是入口js文件
// 其他配置
}
};
api/login.js // 登录api接口
import request from '@/utils/request';
// 获取token
export function login(params) {
return request({
url: '/auth/auth/token',
method: 'post',
headers: { // 可进行headers的配置
'Content-Type': 'application/x-www-form-urlencoded'
},
params: params, // axios参数,自动拼接在url后边,以key=value形式
data: params, // axios参数,在body里面
auth: { // axios basic auth验证
username: "username",
password: "password"
}
});
}
router/index.js
import Vue from "vue";
import Router from "vue-router";
// 第三方库需要use一下才能用
Vue.use(Router)
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
export const defaultRoutes = [
{
path: "/",
component: () => import("@/views/login"),
hidden: true,
},
{
path: "/login",
name: "登录",
component: () => import("@/views/login"),
meta: { title: "登录", icon: "dashboard", affix: true },
hidden: true,
},
{
path: "/stage",
name: "平台",
component: () => import("@/views/stage"),
meta: { title: "平台", icon: "dashboard", affix: true },
hidden: true,
},
{
path: "/404",
name: "404",
component: () => import("@/views/error-page/404"),
meta: { title: "404", icon: "dashboard", affix: true },
hidden: true,
},
{
path: "/401",
name: "401",
component: () => import("@/views/error-page/401"),
meta: { title: "401", icon: "dashboard", affix: true },
hidden: true,
},
{
path: "/500",
name: "500",
component: () => import("@/views/error-page/500"),
meta: { title: "500", icon: "dashboard", affix: true },
hidden: true,
},
]
const router = new Router({
routes: defaultRoutes
});
export default router
store/index.js(状态管理)
import Vue from "vue"
import Vuex from "vuex"
import getters from "./getters"
import settings from "./modules/settings"
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
settings,
},
getters
})
export default store
store/modules/settings
const state = {
navbar: "", // 面包屑导航
collapse: false // 侧边栏是否收缩
}
const mutations = {
CHANGE_NAVBAR: (state, name) => {
state.navbar = name;
sessionStorage.setItem("navbar", name);
},
CHANGE_COLLAPSE: (state, flag) => {
state.collapse = flag;
},
}
const actions = {
changeNavbar ({ commit }, name) {
commit("CHANGE_NAVBAR", name)
},
changeCollapse ({ commit }, flag) {
console.log(flag)
commit("CHANGE_COLLAPSE", flag)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
结语
这次就暂时写这么多,其中代码部分是参考vue-element-admin的代码。下篇文章开始出现差异化,自定义配置页面的布局及侧边栏,面包屑导航等。