跳到主要内容

服务端交互


服务端交互说明

数据服务是一个应用的灵魂,它驱动着应用的各个功能模块的正常运转。我们在 service 模块封装了服务端交互,通过 API 的形式可以和任何技术栈的服务

服务交互流程

服务交互流程如下: 1.组件内调用 service 服务 API 2.service 服务 API 封装请求数据,通过 request.js 发送请求 3.组件获取 service 返回的数据,更新视图数据或触发其它行为 我们以登录为例,Login.vue 组件内,用户输入账号密码,点击登录,调用 services/user/login api

<template>
...
</template>

<script>
import { login } from '@/services/user.js'
export default {
name:’login’,
methods: {
onSubmit (e) {
e.preventDefault()
this.form.validateFields((err,values) => {
if (!err) {
this.logging = true
login(values).then(res => this.afterLogin(res))
}
})
}
}
}
</script>

services/user/login 封装账户密码数据,通过 request.js 发送登录服务请求

import { baseUrl } from './baseUrl.js'

/**
* 登录服务
* @parameter 用户登录信息
* @returns {Promise<AxiosResponse<T>>}
*/
export function login (parameter) {
return axios({
url: baseUrl + '/system/jwtLogin',
method: 'post',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
data: parameter
})
}

Login.vue 获取登录服务返回的数据,进行后续操作

<template>
...
</template>

<script>

import { login } from '@/services/user.js'
export default {
name:’login’,
methods: {
onSubmit (e) {
e.preventDefault()
this.form.validateFields((err,values) => {
if (!err) {
this.logging = true
login(values).then(res => this.afterLogin(res))
}
})
}
loginSuccess(res) {
if(res.statusCode == 200){ //登录成功
....
} else { //登录失败
this.errMessage = err.message
}
}
}
}
</script>

使用通用的请求方法

//Login.vue
<template>
...
</template>

<script>
export default {
name:’login’,
methods: {
onSubmit (e) {
e.preventDefault()
this.form.validateFields((err,values) => {
if (!err) {
this.logging = true
this.$post(/system/jwtLogin’, values) .then(res => this.afterLogin(res))

})
}
loginSuccess(res) {
if(res.statusCode == 200){ //登录成功
....
} else { //登录失败
this.errMessage = err.message
}
}
}
}
</script>
//Common.js

import { axios } from '@/utils/request'
import { baseUrl } from './baseUrl.js'
import qs from 'qs'
// axios.defaults.withCredentials=true //允许携带cookie

//post
export function postAxiosRequest(url,parameter) {
return axios.post(url, qs.stringify(parameter));
}
// get
export function getAxiosRequest(url,parameter) {
return axios.get(url, qs.stringify(parameter));
}

baseUrl配置

你可以在项目根目录下的环境变量文件(.env 和 .env.development)中配置你的 API 服务 base url 地址。

  1. 开发环境
//.env.development文件
VUE_APP_API_BASE_URL=http://localhost:8080 //基本请求地址
VUE_APP_API_JOB_BASE_URL=http://localhost:8081 //xxl-job请求配置
  1. 生产环境
//.env.productiont文件
VUE_APP_API_BASE_URL=https://vue.misboot.com //基本请求地址
VUE_APP_API_JOB_BASE_URL=https://vue.misboot.com

跨域设置

在 vue.config.js 文件中配置代理:

model.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://vue.misboot.com',
ws: true,
changeOrigin: true,
pathRewrite: { '^/api': '/' },
}
}
},
}

TIP 此代理配置仅适用于开发环境,生产环境的跨域代理请在自 己的web服务器配置。

Mock模拟数据

Mock模拟数据是用的是mock.js的语法实现。暂时只有在门户页面使用到,以获取图表数据为例:

  1. 本地门户首页mock
// mock\controller\dashboard.js

module.exports = [{
url: '/dashboard/lineChart',
type: 'post',
response: (config) => {
const { type } = config.body
console.log(type)
return {
data: {
xData: xDataList[type],
yData: lineData(type),
lastData: lineData(type),
},
code: 200,
message: '数据获取成功',
}
},
},
}


//src\services\dashboard.js

import { request} from '@/utils/mock.js'
import qs from 'qs'
/**
* @description 获取card echarts图
* @param {string} type 类型
* @param {currentKey} 销售或访问量等类型
* @param {string} startTime 开始时间 可选
* @param {string} endTime 结束时间 可选
* @returns {Object}
*/
export function getLineChartData(data) {
return request.post('/dashboard/lineChart', qs.stringify(data));
}


//组件页面
<template>
.....
</template>
<script>
import { getLineChartData } from '@/services/dashboard';
export default {
name: 'index',
data() {
return {
currentKey: 'sale',
currentType: 'day',
lineData: {},
};
},
methods: {
async getLineData() {
const { currentType: type, currentKey } = this;
const { data } = await getLineChartData({ type, currentKey });
this.lineData = data || [];
},
}
};
</script>
  1. 门户设计mock数据
// mock\controller\portal.js
//接口都需要带/mockXHR,为了区分mock和真实数据接口
module.exports = [{
url: '/mockXHR/portal/barChart',
type: 'post',
response: (config) => {
const {
type
} = config.body
console.log(type)
return {
xData: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'],
seriesData: [{
name: "篮球",
data: [30, 40, 50, 50, 55, 60, 40],
},
{
name: "羽毛球",
data: [60, 60, 90, 90, 120, 120, 90],
},
{
name: "乒乓球",
data: [40, 40, 60, 60, 80, 80, 60],
},
],
}
},
}

]

//src\services\apiByPortal.js

import request from '@/utils/mock'
import axios from '@/utils/requestByPortal'
import qs from 'qs'

/**
* @description 门户管理数据请求方法
* @param {string} method 请求方式
* @param {string} url 接口地址
* @param {Object} data 参数
* @returns {Object}
*/
export function axiosRequest(method, url, data) {
if (method == 'post') {
if (isMock) {
return request.post(url, data);
} else {
return axios.post(url, data);
}
} else {
if (isMock) {
return request.get(url, data);
} else {
return axios.get(url, data);
}
}
}
// 判断是否请求的是mock数据
function isMock(url) {
return url.indexOf("/mockXHR/") != -1
}
//组件页面
<template>
.....
</template>
<script>
import { axiosRequest } from "@/services/apiByPortal";
export default {
name: 'index',
data() {
return {};
},
methods: {
getData(){
axiosRequest(method,url,params).then((res) => {}
}
}
};
</script>