小程序登录流程
这里我们是使用Taro来开发小程序,Taro 是一个开放式跨端跨框架解决方案,支持使用React/Vue/Nerv 等框架来开发 微信 / 京东 / 百度 / 支付宝 / 字节跳动 / QQ / 飞书 小程序 / H5 / RN 等应用;Taro3.0中可以使用完整的React/Vue/Vue3/Nerv开发体验,具体请参考
这里我们使用React来开发小程序的登录流程
一、封装小程序登录方法
/src/utils/config.js
import Taro from '@tarojs/taro'
// 获取小程序环境版本
const { envVersion } = Taro.getAccountInfoSync().miniProgram;
const domainOptions = {
develop: "https://*****",//开发版
trial: "https://*****",//体验版
release: "https://*****",//正式版
}
//不同环境的域名
export const DOMAIN = domainOptions[envVersion];
// token 名字
export const Authorization = 'token'
/src/utils/login.js
import Taro from "@tarojs/taro";
import { Authorization } from "./config";
import { getOpenId } from "../api";
/**
* 重新登录
*/
export const userLogin = () => {
return new Promise(async (resolve, reject) => {
try {
const res = await refreshLogin();
resolve(res);
} catch (err) {
reject(err);
}
});
};
/**
* 重新登录
* token不存在或session失效时
*/
export const refreshLogin = () => {
Taro.removeStorageSync(Authorization);
return new Promise(async (resolve, reject) => {
try {
const code = await getWxCode();
// 通过调用后端接口,换取token
const res = await getOpenId({ code });
// 没有登录,去登录页面
if (res.code == 1001) {
Taro.redirectTo({ url: "/pages/user/login" });
return;
}
resolve(res);
} catch (err) {
reject(err);
}
});
};
/**
* 获取 小程序的code
*/
export const getWxCode = async () => {
return new Promise((resolve) => {
// 通过小程序的login接口获取小程序code,
Taro.login({
success(res) {
if (res.code) {
resolve(res.code);
} else {
Taro.showToast({
title: "登录失败,请重新进入小程序",
icon: "none",
duration: 3000,
});
}
},
});
});
};
二、封装request请求
/src/utils/request.js
import Taro from "@tarojs/taro";
import { Authorization, DOMAIN } from "./config";
import { userLogin } from "./login";
export const request = (params) => {
return new Promise((resolve, reject) => {
let { method = "POST", url, data = {}, header = {} } = params;
let token = Taro.getStorageSync(Authorization);
console.log("请求参数:", params);
// 设置token
let defaultHeader = { Cookie: token };
Taro.request({
method,
url: /^http(s?):\/\//.test(url) ? url : DOMAIN + url,
data, //请求参数
credentials: "include",
header: Object.assign(defaultHeader, header), //相同header设置将覆盖默认
success(res) {
// 如果token不存在
if (!token) {
const cookie = res.cookies.find(item => item.includes('JSESSIONID='))
Taro.setStorageSync(Authorization, cookie);
}
let { code } = res.data;
if (code === 555) {
// token失效,重新获取小程序code去后台换取token
userLogin().then(() => {
resolve(request(params));
});
return;
}
resolve(res.data);
},
complete(res) {
if (res.statusCode !== 200) {
Taro.showToast({
icon:'error',
title: '网络出错啦!'
})
}
},
fail(err) {
Taro.showToast({
icon:'error',
title: '网络出错啦!'
})
reject(err);
},
});
});
};
为了防止有人采坑,这里需要重点注意下,
- 如果develop和trial设置的地址和release一样,res.cookies的长度会有多个,如 [“acw_tc=xxxxx;path=/;HttpOnly;Max-Age=1800”, “JSESSIONID=xxxxxx; Path=/; HttpOnly”],
- 否则只有一个[“JSESSIONID=xxxxxx; Path=/; HttpOnly”]
三、进入小程序时需要做的事情
import React, { Component } from "react";
import { Provider } from "react-redux";
import Taro, { getCurrentInstance } from "@tarojs/taro";
import { userLogin } from "@/utils/login";
import dva from "@/utils/dva";
import models from "./models/index";
// 这里集成了dva,想要了解Taro如何集成dva可以关注后续文章
const dvaApp = dva.createApp({
initialState: {},
models,
});
const store = dvaApp.getStore();
const rulePath = [
"pages/user/login"
];
class App extends Component {
constructor() {
super(...arguments);
}
onLaunch(options) {
Taro.clearStorageSync();
}
onShow(){
const router = getCurrentInstance().router;
// 如果当前页面是登录页面,直接return
if (rulePath.includes(router.path)) {
return;
}
const state = store.getState();
const { isUpload } = state.global;
// 在表单填写的时候,如果存在图片上传在onChange后会触发onShow生命周期,
// 这里使用了dva状态管理去判断是否进行上传图片
if (isUpload) {
store.dispatch({ type: "global/getUploadStatus", payload: false });
return;
}
// 用户登录
userLogin().then((res) => {
// 用户没有登录,跳转到登录页面
if (res.code == 1001) {
Taro.redirectTo({
url: "/pages/user/login",
});
return;
}
// 获取用户信息
if (res.code == 200) {
store.dispatch({
type: "global/getUserInfo",
payload: res.result,
});
}
});
}
render() {
return <Provider store={store}>{props.children}</Provider>;
}
}
export default App;
到这里小程序基于session登录机制基本算结束了