- vue打包后只会保留js,css,html文件
- 所以需要把 *.proto 文件转化成 *.js 文件
- 整体思想封装一个request.js来统一管理发起的请求(pb格式的请求)
- 把接口统一封装到api文件夹中
- 使用api里的方法来请求后台接口,后续只需要考虑API里的request,response,请求参数
-
在src目录下新建一个proto目录,来存放后台提供的*.proto文件

-
将*.proto文件生成src/proto/proto.js
该命令可以直接生成proto.js
npx pbjs -t json-module -w commonjs -o src/proto/proto.js src/proto/*.proto-w参数可以指定打包js的包装器,这里用的是commonjs当后期服务端经常性更新proto文件时,每次执行命令是一件很痛苦的事情,所以我们可以把命令提取到package.json的scripts中:
package.json
"scripts"``: {"proto"``:"pbjs -t json-module -w commonjs -o src/proto/proto.js src/proto/*.proto"``,},然后直接使用 npm run proto 或者 yarn proto
-
封装request.js
//封装request.js文件 /utils/request.jsimport axios from'axios'import protoRoot from'@/proto/proto'import protobuf from'protobufjs'import {Toast} from"vant"``;//toast提示——可以更换自己的toastimport {serverHost} from"../../config/service"``;import store from'../store'const httpService = axios.create({baseURL: serverHost,``//后台服务地址timeout: 60000,method:'post'``,headers: {'X-Requested-With'``:'XMLHttpRequest'``,'Content-Type'``:'application/octet-stream'``,},responseType:'arraybuffer'})httpService.interceptors.request.use(config => {//传递tokenconfig.headers[``'access-token'``] = store.state.tokenreturnconfig})// 请求体message// const PBMessageRequest = protoRoot.lookup('GetShopListRequest')// 响应体的messageconst PBMessageResponse = protoRoot.lookup(``'GetShopListByTagResponse'``)//处理返回的结果集通用的解析方法 ——对照proto.jsfunctiongetMessageTypeValue(msgType) {const PBMessageType = protoRoot.lookup(``'Result'``)const ret = PBMessageType.fields[msgType]returnret}// 将请求数据encode成二进制,encode是proto.js提供的方法functiontransformRequest(data,reqType) {const PBMessageRequest = protoRoot.lookup(reqType)returnPBMessageRequest.encode(data).finish()}functionisArrayBuffer (obj) {returnObject.prototype.toString.call(obj) ==='[object ArrayBuffer]'}functiontransformResponseFactory(responseType) {returnfunctiontransformResponse(rawResponse) {// 判断response是否是arrayBufferif(rawResponse ==null|| !isArrayBuffer(rawResponse)) {returnrawResponse}try{const buf = protobuf.util.newBuffer(rawResponse)const PBMessageType = protoRoot.lookup(``'Result'``)// decode响应体const decodedResponse = PBMessageType.decode(buf)``//PBMessageResponse.decode(buf)if(decodedResponse.data && responseType) {const model = protoRoot.lookup(responseType)decodedResponse.data.value = model.decode(decodedResponse.data.value)}returndecodedResponse}catch(err) {returnerr}}}/**** @param {*} msgType 接口名称* @param {*} requestBody 请求体参数* @param {*} responseType 返回值*/functionrequest(msgType, requestBody, responseType, requestType) {// 构造公共请求体:PBMessageRequestconst reqData = requestBody// 将对象序列化成请求体实例const PBMessageRequest = protoRoot.lookup(requestType)const req = PBMessageRequest.create(reqData)// PBMessageRequest.encode(data).finish()// 这里用到axios的配置项:transformRequest和transformResponse// transformRequest 发起请求时,调用transformRequest方法,目的是将req转换成二进制// transformResponse 对返回的数据进行处理,目的是将二进制转换成真正的json数据const toast = Toast.loading({duration: 0,// 持续展示 toastforbidClick:true``,message:'加载中...'``,});returnhttpService.post(msgType, req, {transformRequest: (data)=> transformRequest(data,requestType),transformResponse: transformResponseFactory(responseType)}).then(({data, status}) => {// 对请求做处理if(status !== 200) {const err =newError(``'服务器异常'``)throwerr}console.log(data)data.data = data.data ? data.data : {value:{code: 0}}Toast.clear();returndata.data.value},(err) => {Toast.fail(err.message)// console.log(err)// Toast.clear();throwerr})}// 在request下添加一个方法,方便用于处理请求参数request.create =function(protoName, obj) {console.log(obj)returnobj}exportdefaultrequest -
调用request.js
// /api/shop.js文件import request from'../utils/request'// params是object类型的请求参数// GetShopListRequest 是定义好的请求体model// GetShopListByTagResponse 是定义好的响应model// /talk/shopListByTag 是接口名称// 后面如果再添加接口直接以此类推exportfunctiongetShopList (params) {const req = request.create(``'GetShopListRequest'``, params)returnrequest(``'/talk/shopListByTag'``, req,'GetShopListByTagResponse'``,'GetShopListRequest'``)}为了统一管理api接口,所以我在这里封装了一下api的各个接口,为了后续的使用
-
在.vue中使用接口
//Vue文件中的使用<script>import { getShopList } from"../api/shop"``;exportdefault{methods: {//使用api文件下的shop.js请求服务端//param为请求参数,参照proto文件内的参数形式传递getList() {let param = {'countryCode'``:'CN'``,'type'``:'2'``,'language'``:'zh-cn'}getShopList(param).then(res => {console.log(res)}).``catch``((err) => {console.log(err)})}}}</script>总结:
- 将后端提供的所有的proto文件拷进
src/proto文件夹 - 运行
npm run proto 或者 yarn proto生成proto.js - 根据接口枚举在
src/api下写接口 .vue文件中使用接口。
- 将后端提供的所有的proto文件拷进