上一章我们详解了项目的架构目录,这一章主要学习对接口的封装。
网络请求封装是每个前端项目必不可少的一项,有利于方便统一管理,比如在请求头统一加上后台校验数据,这样就没必要在每个接口中都写一遍了嘛,这也是面向对象编程的一个好的提现。
我们这次选用的是axios插件,这个插件优点还是蛮多的,支持promise,可以拦截请求和拦截响应,客户端支持防御XSRF攻击等等,那么我们就开始吧。
一、安装axios
老规矩,在控制台中输入:
npm install axios -S
二、对axiaos做封装
我们在request目录的index.js文件中,
导入axiaos插件,主角。
导入用到的element-ui中的Message弹窗组件,主要用作提示报错,如:接口请求报错了,可以在响应拦截中弹窗提示相应信息。
导入store,用于设置全局的状态管理,比如常用到的用户信息,站点管理这些。
导入auth,封装有获取token方法的插件,如:获取浏览器缓存中的token信息。
导入路由router,用于路由跳转,如:后台返回登录信息过期,那么我们在请求响应拦截捕获到了,然后我们就可以直接做路由跳转到登录页面了。
并写入相应的请求拦截和响应拦截。
import axios from 'axios'
import { Message } from 'element-ui' //element弹窗
import store from '@/store' //登录信息
import { getToken } from '@/utils/helper/auth.js' //获取token
import Router from '@/router/index.js' //路由对象
const service = axios.create({
timeout: 10000,
})
// request interceptor
//请求拦截
service.interceptors.request.use(
(config) => {
//header存放token-一般接口要求
config.headers['token'] = getToken()
//设置请求接口
service.prototype.requestUrl = config.url
return config
},
(error) => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
//响应拦截
service.interceptors.response.use(
/**
* 这里会返回http请求的信息,如数据、状态码
*/
(data) => {
data = data.data
let res = {}
if (data.code == '0') {
console.log('接口请求数据正常')
} else if (data.code == 201 || data.code == '9001') {
Message({
message: '账号信息已过期,请重新登录',
type: 'warning',
})
//清空用户信息
store.commit('user/logout')
Router.push({ path: '/login' })
} else {
Message({
message: data.msg,
type: 'error',
})
}
// 处理返回格式-自定义返回所有数据或数据包裹指定数据
// eslint-disable-next-line no-prototype-builtins
if (data.hasOwnProperty('data') && data.data != null && !data.total && service.prototype.requestUrl.indexOf('auth') == -1) {
res = data.data
} else {
res = data
}
return res
},
(error) => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000,
})
return Promise.reject(error)
}
)
export default service
加好上面的内容后,补充一下需要导入的内容。在utils文件夹下创建helper文件夹,然后新建auth.js文件,加入下面获取token的方法。
utils/helper/auth.js内容:
const TokenKey = 'token'
export function getToken() {
return localStorage.getItem(TokenKey)
}
export function setToken(token) {
return localStorage.setItem(TokenKey, token)
}
export function removeToken() {
return localStorage.removeItem(TokenKey)
}
补充一下store中的内容:
store/modules/user.js内容:
export default {
namespaced: true,
state: {
userInfo: {
id: null,
account: '',
realName: '',
companies: '',
sites: null,
},
},
mutations: {
setUserInfo(state, param) {
state.userInfo = param
},
logout(state, param) {
state.userInfo = param
},
},
}
补充好上面的内容后,然后做一下全局配置,这样可以在vue文件中通过this调用了。
三、全局配置
api目录下创建index.js文件
导入Vue,通过原型继承,实现全局注册。
导入string的toLowerCaseBar,这个方法是用来将小写驼峰的字符串转成小写横杆的字符串,比如:getDataApi转成get-data-api,主要的作用是做一个请求方法的统一管理。
并写入下面内容:
import Vue from 'vue'
import { toLowerCaseBar } from '@/utils/helper/string.js' // 格式(小写驼峰)转 格式(小写横杠)
/**
* 页面调用API目录方法
* @func ajax
* @param {String} route 请求路径
* @param {Object} param 接口参数
*/
const ajax = (route, param) => {
let arr = route.split('/') // 目录 -> 文件 -> 方法
// 获取组s件
let components = require('./' + toLowerCaseBar(arr[0]) + '/' + toLowerCaseBar(arr[1]) + '.js')[arr[2]]
return components(param)
}
/**
* 页面调用API目录方法
* @func ajax
* @param {String} route 请求路径
* @param {Object} param 接口参数
*/
Vue.prototype.$ajax = ajax
export default ajax
补充一下上述导入的string.js文件,同样在utils文件夹下的helper文件夹,创建string.js,为啥叫string.js呢?
主要类似一个类吧,主要应用于字符串类型的操作,字符串截取,字符串转换等等。
然后添加以下代码:
/**
* 格式(小写驼峰)转 格式(小写横杠)
* @func toLowerCaseBar
*/
export const toLowerCaseBar = (data) => {
let res = ''
if (data) {
res = data.replace(/[A-Z]/g, (item) => `-${item.toLowerCase()}`)
}
return res
}
封装的工作做好了,然后在main.js文件中做一下全局导入,通过import 导入api下的index.js文件即可。
....
import 'element-ui/lib/theme-chalk/index.css' //样式文件一定要引入
import './api/index.js'
//载入路由
....
四、添加mock数据-测试
现在我们在搭建框架的过程中,后台应该还没出接口供我们测试,那么就需要我们去造数据。
打开cmd,安装我们所用到的工具,mockJS
npm install --save-save mockjs
然后我们在src目录下创建service文件夹,创建两个文件,index.js,test.mock.js主要用来存放虚拟接口数据的。
index.js文件代码如下:
import Mock from 'mockjs'
//入口文件
Mock.setup({
timeout: '500-800',
})
const context = require.context('./', true, /\.mock.js$/)
context.keys().forEach((key) => {
Object.keys(context(key)).forEach((paramKey) => {
Mock.mock(...context(key)[paramKey])
})
})
export default context
这个文件的作用将service下的每个数据模块导入然后再全局导出,这样我们在开发的时候,就可以做虚拟数据的按模块独立出来。例如下面的test.mock.js文件,可以作为一部分接口数据。
test.mock.js代码如下:
import Mock from 'mockjs'
const { Random } = Mock
export default [
RegExp('/login.*'),
'get',
{
'range|50-100': 50,
'data|10': [
{
// 唯一 ID
id: '@guid()',
// 生成一个中文名字
cname: '@cname()',
// 生成一个 url
url: '@url()',
// 生成一个地址
county: Mock.mock('@county(true)'),
// 从数组中随机选择一个值
'array|1': ['A', 'B', 'C', 'D', 'E'],
// 随机生成一个时间
time: '@datetime()',
// 生成一张图片
image: Random.dataImage('200x100', 'Mock Image'),
},
],
},
]
做好之后,在main.js文件中导入:
做好全局导入之后,我们就可以通过请求来做测试了。
简单写一个请求数据的方法,在api文件夹下创建login文件夹,然后在login文件夹下创建auth-api.js,添加下面内容:
导入request,前面封装的网络请求方法
导入url,全局配置文件中的请求域。config.index.js代码如下:(域名记得换成自己本机nodeJS运行服务的域名)
/* eslint-disable no-undef */
const CONFIG = {
//开发环境
development: {
url: 'http://192.168.0.101:8080', //本机ip地址域名
},
//生产环境
production: {
url: 'https://getman.cn/mock', //生产环境的请求域名
}
}
export default CONFIG[process.env.NODE_ENV]
auth-api.js代码入下:
import request from '@/utils/request/index.js'
import config from '@/config/config.index.js'
/**
* @description 登录
* @param {JSON} param
* @returns
*/
export const loginApi = (param) => {
return request({
method: 'post', // 请求方式: GET、POST
url: config.url + '/login',
data: param, // 请求参数
}).then((res) => {
return new Promise((resolve) => {
resolve(res)
})
})
}
然后我们在App.vue中添加一个点击方法,用作调起请求用的。
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<el-button type="primary" @click="getData">测试按钮</el-button>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
methods: {
getData() {
this.$ajax('login/authApi/loginApi', {}).then(res => {
console.log(res)
}).catch(rej => {
console.log(rej)
})
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
点击测试按钮,就可以正常调用网络请求的方法。
本章内容就到这里结束吧,下一章为大家讲一下如何去实现权限管理。