写这个配置的目的主要是 满足多baseURL请求需求,不喜欢使用 fly- get post那套 不可能傻乎乎的 每个 baseURL写一个 fly-get post;
我的项目地址https://gitee.com/ming34902/mpvue-quick-test1.git 放码云了,没有放github
基于mpvue官方mpvue-quickstart 项目模板,配置fly+vuex+easymock实现多baseURL请求配置,token拦截登录等功能,主要是方便 自己 后续 要是老板要求用坑爹 mpvue 写微信小程序 准备,本来用原生写的挺好的;
一、 准备工作
1. 下载mpvue官方mpvue-quickstart 项目模板,
http://mpvue.com/mpvue/quickstart/ 根据官方指引 自行安装 mpvue-quickstart 项目模板;
吐槽:官方mpvue2.0 之前版本 出现依赖报错问题,清空依赖 重新 npm install 都无法解决 百思不得其解,百度都找不出来,后面去github看mpvue的issues上才发现这问题是最近 mpvue更新出现 依赖bug报错,导致之前创建的几个mpvue初始项目模板丢弃,用mpvue2.0版本 以及mpvue-quickstart项目模板为基础 重新二次 配置自己想要的(fly多host请求,token拦截) 初始化的项目模板 ;
上述问题,mpvue2.0版本以下的项目 运行npm run dev(官方依赖问题)报错:
[mpvue-loader] need "fileExt" option in file "build/vue-loader.conf.js"
Module build failed: Error: [mpvue-loader] need "fileExt" option in file "build/vue-loader.conf.js",init a new project and copy the directory "build/" to this porject, or just check the "fileExt" option
解决:使用mpvue2.0版本 以及mpvue-quickstart项目模板,重新写呗;
其他mpvue问题 就不多吐槽了,反正满头包.....
2. HTTP 请求终极解决方案flyio ,有些类似axios
https://wendux.github.io/dist/#/doc/flyio/readme flyio官方文档
3. easyMock 在线mock平台
就是不用写后台,直接自己创个项目 写接口配置(api+method+json)模拟后台api请求 返回数据,非常方便;
https://easy-mock.com
二、开始配置文件
假设你已准备好 mpvue-quickstart 项目模板文件,以及 微信web开发工具 appid 、easymock等;
1. 环境配置 config目录dev.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
// BASE_API: '"https://ao-api-test.xxx.com"',
BASE_API_UAA: '"https://easy-mock.com/mock/xxxx1/lisa-uaa"', // 单点登录
BASE_API: '"https://easy-mock.com/mock/xxx8/lisa-mpvue-test1"', // 提供常规业务需求
})
2. flyio 写request.js 写请求,加了白名单、token拦截检查登录
import Fly from 'flyio/dist/npm/wx';
// import Fly from 'flyio' // 引用失败
// 获取白名单
import whiteList from '@/utils/whiteList';
const fly = new Fly();
//设置超时
fly.config.timeout = 20000;
// const Authorization = wx.getStorageSync('Authorization');
//添加请求拦截器
fly.interceptors.request.use((request) => {
console.log('request', request);
// 不显示加载页面的接口
if (whiteList.loading.indexOf(request.url) === -1) {
// 隐藏loading遮罩
}
wx.showLoading({
'title': '加载中',
'mask': true
});
// 请求资源服务器时,不添加token
if (whiteList.nullHeaderToken.indexOf(request.url) !== -1) {
request.timeout = 30000; // 请求超时
request.headers = {
'content-type': 'application/json',
'X-Tag': 'flyio'
};
return request;
}
const Authorization = wx.getStorageSync('Authorization');
// 延迟发请求 等 getStorageSync 存储
setTimeout(() => {
// 无token 则跳转登陆页
if (Authorization) {
// 给所有请求添加自定义header
request.timeout = 30000;
request.headers = {
'content-type': 'application/json',
'X-Tag': 'flyio',
'Authorization': 'Bearer ' + Authorization
};
} else {
// promise.reject(request)
console.log('没有token跳转登录');
setTimeout(() => {
wx.redirectTo({
url: '/pages/login/main'
});
}, 300)
}
return request;
}, 300)
}, (error,promise) => {
// Do something with request error
console.log(error); // for debug
promise.reject(error)
});
//添加响应拦截器,响应拦截器会在then/catch处理之前执行
fly.interceptors.response.use(
(response) => {
wx.hideLoading();
console.log('interceptors数据', response.data);
//只将请求结果的data字段返回
return response.data
},
(err, promise) => {
wx.hideLoading();
let msg = '';
if (err.status === 0) {
msg = '网络连接异常'
} else if (err.status === 1) {
msg = '网络连接超时'
} else if (err.status === 401) {
msg = '用户未登录'
} else {
if (err.response.data.message) {
msg = err.response.data.message
} else {
msg = '请求数据失败,请稍后再试'
}
}
wx.showToast({
title: msg,
icon: 'none',
duration: 2000
});
return promise.resolve(err)
}
);
// Vue.prototype.$http=fly //将fly实例挂在vue原型上
export default fly
3. baseURLConfig.js
/**
* 定义当前环境的各个API的 baseURL
*/
const baseURL = {
'NORMAL': process.env.BASE_API,
'UAA': process.env.BASE_API_UAA
};
export default baseURL;
4.业务api 多baseURL,api目录home.js
import fly from '@/utils/request'
import baseURL from '@/utils/baseURLConfig'
import qs from 'qs'
export function userLogin(data) {
return fly.request({
baseURL: baseURL.UAA, // 使用 BASE_API_UAA
url: '/oauth/token',
method: 'post',
data: qs.stringify(data)
})
}
export function getHomeList(data) {
return fly.request({
baseURL: baseURL.NORMAL, // 使用 BASE_API
url: '/home/index',
method: 'post',
data: qs.stringify(data)
})
}
5.常规使用- index.vue 首页
import * as HomeApi from '@/api/home'
export default {
....
methods: {
getData() {
const toParams = { id: 1 } // 请求参数
HomeApi.getHomeList(toParams).then((res) => {
console.log('getHomeList()', res.data)
}).catch((error) => { console.log(error) })
},
}
}
6. vuex -action调用
store目录user.js
import { userLogin } from '@/api/user'
const user = {
state: {
token: '',
name: '',
openId: '初始openId',
userInfo: {}
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token;
wx.setStorageSync('Authorization', token);
},
SET_OPEN_ID: (state, openId) => {
state.openId = openId;
wx.setStorageSync('openId', openId);
},
SET_NAME: (state, name) => {
state.name = name
},
SET_USER_INFO: (state, userInfo) => {
state.userInfo = userInfo
}
},
actions: {
// 登录
async Login({ commit }, userInfo) {
// 方法一 async+await 成功
const res_data = await userLogin(userInfo)
commit('SET_TOKEN', res_data.data.access_token)
commit('SET_OPEN_ID', res_data.data.openId)
// 登录成功 跳转首页
wx.switchTab({
url: '/pages/index/main'
});
}
}
}
export default user
具体使用login.vue
import { mapActions } from 'vuex'
export default {
....
methods: {
...mapActions('user', [
'Login'
]),
async doLogin() {
const that = this
const check_res = that.checkLoginParams()
if (check_res) {
wx.showLoading({
title: '登录中...', //提示的内容,
mask: true, //显示透明蒙层,防止触摸穿透,
success: (res) => { console.log(res) }
});
// 获取微信账号登录时的code
let resCode = wx.getStorageSync('resCode')
const params = {
'code': resCode,
'username': that.usernameInput,
'password': that.pwdInput
}
await that.Login(params)
}
},
// 账号 和 密码 校检
checkLoginParams: function() {
const that = this
let {usernameInput, pwdInput} = that._data
if (usernameInput === '') {
wx.showToast({
title: '请填写账号',
icon: 'none',
duration: 1500
})
return
}
if (pwdInput === '') {
wx.showToast({
title: '请填写密码',
icon: 'none',
duration: 1500
})
return
}
return true
}
}
....
}
三、文件目录结构注释md
|-- 项目
|-- .babelrc # 集成es6环境
|-- .editorconfig # 编辑器的配置
|-- .eslintignore # 表示忽略语法检查的目录文件
|-- .eslintrc.js # eslint 严格代码规范
|-- .gitignore # 表示文件内写好的文件路径都会被Git忽略,不会被提交到代码仓库
|-- .postcssrc.js # 对css前缀的一些解析
|-- index.html # 入口页面
|-- package.json # npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
|-- README.md # 项目介绍
|-- build # 脚本目录
| |-- build.js # 生产环境构建脚本
| |-- check-versions.js # 运行本地构建服务器,可以访问构建后的页面
| |-- dev-client.js # 开发服务器热重载脚本,主要用来实现开发阶段的页面自动刷新
| |-- dev-server.js # 运行本地开发服务器
| |-- utils.js # 构建相关工具方法
| |-- vue-loader.conf.js # vue垫片配置
| |-- webpack.base.conf.js # webpack配置文件
| |-- webpack.dev.conf.js # webpack开发环境配置
| |-- webpack.prod.conf.js # webpack生产环境配置
|-- config # 项目配置
| |-- dev.env.js # dev开发环境
| |-- index.js # 项目配置文件
| |-- prod.env.js # prod生产环境
|-- dist # bulid 构建成功后 生产的目录
|-- src # 开发目录
| |-- app.json # 路由、tab等配置
| |-- App.vue # 根组件
| |-- main.js # 预编译入口文件
| |-- api # api接口目录
| | |-- home.js
| | |-- user.js
| |-- components # 公共组件目录
| | |-- card.vue
| |-- pages # 页面目录
| | |-- index # 首页
| | | |-- index.vue
| | | |-- main.js
| | | |-- style.scss
| | |-- login # 登录页
| | | |-- login.vue
| | | |-- main.js
| | | |-- style.scss
| | |-- logs # 登录日志页
| | | |-- index.vue
| | | |-- main.js
| | | |-- main.json
| | |-- search # 搜索页
| | |-- index.vue
| | |-- main.js
| | |-- style.scss
| |-- store # vuex目录
| | |-- index.js # vuex 注册
| | |-- modules # 业务模块
| | |-- home.js
| | |-- user.js
| |-- style # 样式目录
| | |-- common.css
| | |-- index.css
| | |-- weui.css
| |-- utils # 工具目录
| |-- baseURLConfig.js # baseURL配置
| |-- global.js # 全局数据存储 global
| |-- index.js #
| |-- request.js # fly 请求
| |-- wechat.js # wechat微信原生api
| |-- whiteList.js # 请求白名单
| |-- common # 公共类
| | |-- mixins.js
| | |-- tips.js
| | |-- utils.js
| |-- lib # 图书馆
| |-- amap-wx.js # 高德-wx
|-- static # web静态资源加载目录 不会被wabpack构建
|-- images
|-- common
|-- tabs