接着前一篇内容:https://blog.csdn.net/wwyywwsaber/article/details/123925017
要点:
- 统一url配置
- 统一api请求
- request拦截器
- response拦截器
- 将axios封装成vue插件使用
文件结构:
在src目录下,新建一个http文件夹,用来存放http交互api代码
- config.js:axios默认配置,包含基础路径等信息
- axios.js:二次封装axios模块,包含拦截器等信息
- api.js:请求接口汇总模块,聚合所有模块API
- index.js:将axios封装成插件,按插件方式引入
- modules:用户管理、菜单管理等子模块API
由于需要用到cookie,安装js-cookie依赖
cnpm install js-cookie
将src/components/HelloWorld.vue改为home.vue
在src目录下新建utils文件夹,创建global.js文件
//global.js代码
export const baseUrl = 'http://127.0.0.1:80'
export const backupBaseUrl = 'http://localhost:8002'
export default{
baseUrl, backupBaseUrl
}
在src/http目录下创建config.js文件
import {baseUrl} from '@/utils/global'
export default{
method: 'get',
baseUrl: baseUrl,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
data: {},
timeout: 1000,
withCredentials: true,
responseType: 'json'
}
在src/http目录下创建axios.js文件
import axios from 'axios'
import config from './config'
import Cookies from 'js-Cookie'
import router from '@/router'
export default function $axios (options) {
return new Promise((resolve, reject) => {
const instance = axios.create({
baseURL: config.baseUrl,
headers: config.headers,
timeout: config.timeout,
withCredentials: config.withCredentials
})
instance.interceptors.request.use(
config => {
let token = Cookies.get('token')
if (token) {
config.headers.token = token
} else {
router.push('/')
}
return config
},
error => {
return Promise.reject(error)
}
)
instance.interceptors.response.use(
response => {
return response.data
},
err => {
return Promise.reject(err)
}
)
instance(options).then(res => {
resolve(res)
return false
}).catch(error => {
reject(error)
})
})
}
在src/http下新建modules文件夹,创建login.js文件
import axios from '@/http/axios'
/*
* 系统登录模块
*/
// 登录
export const login = data => {
return axios({
url: 'login',
method: 'post',
data
})
}
// 登出
export const logout = () => {
return axios({
url: 'logout',
method: 'get'
})
}
在src/http目录下创建api.js文件
import * as login from './modules/login'
export default{
login
}
在src/http目录下创建index.js文件
// 导入所有接口
import api from './api'
const install = Vue => {
if (install.installed) { return }
install.installed = true
Object.defineProperties(Vue.prototype, {
// 注意,此处挂载在 Vue 原型的 $api 对象上
$api: {
get () {
return api
}
}
})
}
export default install
打开src/main.js,把global和api挂载进去
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import global from '@/utils/global'
import api from '@/http'
Vue.use(ElementUI)
Vue.use(api)
Vue.config.productionTip = false
Vue.prototype.global = global
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: ' '
})
打开src/router/index.js文件,修改初始定向路径
import Vue from 'vue'
import Router from 'vue-router'
import login from '@/components/login'
import home from '@/components/home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'login',
component: login
},
{
path: '/home',
name: 'home',
component: home
}
]
})
在src/compoments路径下新建login.vue
Login Page
登录
修改src/mock/mock.js文件,模拟token数据
import Mock from 'mockjs'
Mock.mock('http://127.0.0.1:80/login', {
'token': '1234567890'
})
Mock.mock('http://localhost:8080/user', {
'name': '@name',
'email': '@email',
'age|1-10': 5
})
Mock.mock('http://localhost:8080/menu', {
'id': '@increment',
'name': 'menu',
'order|1-20': 5
})
在src/mock目录下创建index.js
import Mock from 'mockjs'
import { baseUrl } from '@/utils/global'
import * as login from './modules/login'
// 1. 开启/关闭[所有模块]拦截, 通过调[openMock参数]设置.
// 2. 开启/关闭[业务模块]拦截, 通过调用fnCreate方法[isOpen参数]设置.
// 3. 开启/关闭[业务模块中某个请求]拦截, 通过函数返回对象中的[isOpen属性]设置.
let openMock = true
// let openMock = false
fnCreate(login, openMock)
/**
* 创建mock模拟数据
* @param {*} mod 模块
* @param {*} isOpen 是否开启?
*/
function fnCreate (mod, isOpen = true) {
if (isOpen) {
for (var key in mod) {
((res) => {
if (res.isOpen !== false) {
let url = baseUrl
if (!url.endsWith('/')) {
url = url + '/'
}
url = url + res.url
Mock.mock(new RegExp(url), res.type, (opts) => {
opts['data'] = opts.body ? JSON.parse(opts.body) : null
delete opts.body
console.log('\n')
console.log('%cmock拦截, 请求: ', 'color:blue', opts)
console.log('%cmock拦截, 响应: ', 'color:blue', res.data)
return res.data
})
}
})(mod[key]() || {})
}
}
}
在src/mock目录新建modules文件夹,创建login.js
/*
* 系统登录模块
*/
// 登录接口
export function login () {
const loginData = {
'code': 200,
'msg': null,
'data': {
'id': null,
'userId': 1,
'token': '77ae89be36504adfb5c09ef71409ea0e',
'expireTime': '2018-09-01T16:24:50.473+0000',
'createBy': null,
'createTime': null,
'lastUpdateBy': null,
'lastUpdateTime': '2018-09-01T04:24:50.473+0000'
}
}
return {
url: 'login',
type: 'post',
data: loginData
}
}
// 登出接口
export function logout () {
const logoutData = {
'code': 200,
'msg': null,
'data': {
}
}
return {
url: 'logout',
type: 'get',
data: logoutData
}
}
更改login.vue中模拟数据的装载
至此,axios和mock封装基本完毕