一、小程序字段监听
utils/listener/src/events.js
/**
* Declare : 订阅事件全局常量 及 注释
*/
'use strict';
module.exports = {
CANCEL_ORDER: 'CANCEL_ORDER', // 取消事件
}
utils/listener/src/listener.js
/**
* declare: 订阅 & 发布
*/"use strict";
import uuid from '@/utils/uuid';let listenerMap = new Map();
// 监听某个事件
function listen({event, id, maintain, callback}) {
if(!event || typeof callback !== 'function') return;if(!listenerMap.has(event)) {
listenerMap.set(event, []);
}listenerMap.get(event).push({
id,
maintain,
callback
});
}function dispatch(event, arg) {
if (listenerMap.has(event)) {
let listenerArr = listenerMap.get(event);
listenerArr = listenerArr.filter((listener) => {
listener.callback(arg);
return listener.maintain;
});
if(listenerArr.length === 0) {
listenerMap.delete(event);
}
}
}// 订阅事件
function subscribe(event, maintain = false) {
if(!event) return console.error('event can not be empty');let id = uuid();
return {
event,
listen: function (callback) {
listen({
event,
id,
maintain,
callback
});
},
unsubscribe: function () {
unsubscribe(event, id);
}
}
}// 取消订阅
function unsubscribe(event, id) {
if(listenerMap.has(event)) {
const listenerArr = listenerMap.get(event);
let index = listenerArr.findIndex((listener) => listener.id === id);
if(index >= 0) {
listenerArr.splice(index, 1);
}
}
}export default {
subscribe,
dispatch
}
utils/listener/index.js
'use strict';
import listener from './src/listener';
import events from './src/events';
export default listener;
export {events};
utils/uuid.js
/**
* Declare : 生成唯一id
*/"use strict";
let ORIGINAL = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
let alphabet = '';
let timeStamp = '';
let timeStampBit = 0;
let bit = 16;let ZERO = '';
let prevSecond = '';
let order = 1;function uuid() {
if(!alphabet || !timeStamp) {
init();
}const seconds = Math.floor((Date.now() - timeStamp) / 1000);
if(prevSecond === seconds) {
order++;
} else {
prevSecond = seconds;
order = 1;
}
const offset = random(alphabet.length);return (
padStartWithZERO(encode(seconds, offset))
+ encode(order, offset)
);
}function init() {
const year = new Date().getFullYear();
timeStamp = Date.UTC(year, 0, 1, -8, 0, 0);
timeStampBit = encode(365 * 24 * 3600);shuffle();
ZERO = alphabet[0];
}function shuffle() {
const alphabetSet = new Set();while (alphabetSet.size < bit) {
const randomNum = random(ORIGINAL.length);
alphabetSet.add(ORIGINAL[randomNum]);
}alphabet = [...alphabetSet].join('');
return alphabet;
}function encode(number, offset = 0) {
var loopCounter = 0;
var done;var str = '';
while (!done) {
str = str + lookup(((number >> (4 * loopCounter)) & 0x0f), offset);
done = number < (Math.pow(bit, loopCounter + 1));
loopCounter++;
}
return str;
}function lookup(index, offset = 0) {
index = (index + offset) % alphabet.length;
return alphabet[index];
}function padStartWithZERO(num = 0, length = timeStampBit) {
let result = String(num);let diff = length - String(num).length;
if(diff > 0) {
while(result.length < length) {
result = ZERO + result;
}
}return result;
}function random(max = 1) {
const randomNum = Math.floor(Math.random() * max);
if(randomNum === random._randomNum) {
return random(max);
} else {
random._randomNum = randomNum;
return randomNum;
}
}export default uuid;
export {encode};
export {shuffle};
export {padStartWithZERO};
使用
传:
cancel() {
const {id} = this.detail
cancelOrder({id}).then(res => {
// 返回上一页
listeners.dispatch(events.CANCEL_ORDER)
uni.navigateBack()
})
},
接:
import listeners from '@/utils/listener/index'
import { events } from '@/utils/listener/index'onLoad() {
this.listenCancelOrder = listeners.subscribe(events.CANCEL_ORDER, true)
this.listenCancelOrder.listen((data) => {
this.active = '0'
this.orderList = []
this.pageIndex = 1
this.loadData()
})
},
onUnload() {
this.listenCancelOrder.unsubscribe()
},
二、信息存储
utils/auth.js
module.exports = {
"COOKIE": "USER_COOKIE", // 用户的登录凭证
'AUTHORIZED': 'AUTHORIZED', // 用户是否授权过小程序
'LOGGED_IN': 'LOGGED_IN', // 用户是否登录
'REGISTERED': 'REGISTERED', // 用户是否已经注册过小程序
'VISIT_GUIDE': 'VISIT_GUIDE', // 是否第一次访问小程序
}
utils/systemConstant.js
/**
* 存储用户id
*/import constant from '@/utils/systemConstant'
export function setToken(token) {
uni.setStorageSync(constant.COOKIE, token);
}export function getToken() {
return uni.getStorageSync(constant.COOKIE)
}export function removeToken() {
uni.removeStorageSync(constant.COOKIE)
}export function setLogIn(val) {
uni.setStorageSync(constant.LOGGED_IN, val);
}export function getLogIn() {
return uni.getStorageSync(constant.LOGGED_IN)
}export function removeLogIn() {
uni.removeStorageSync(constant.LOGGED_IN)
}
/global.js
'use strict'
const globalData = {
set: function(path, value, api) {
path && (globalData[path] = value)
return true
},
get: function(path) {
return path ? globalData[path] : globalData
},
delete: function(path) {
delete globalData[path]
return true
}
}export default globalData
使用:
utils/wechat.js
/**
* 微信登录操作
*/"use strict";
import config from 'config';
import constant from '@/utils/wechat'
import { getToken, setToken, setLogIn } from '@/utils/auth'
import { set } from '@/global'
import { onLogin, getPhone, detailUser } from '@/api/user'
import listeners from '@/utils/listener/index'
import { events } from '@/utils/listener/index'// 获取登录凭证code
export function getCode() {
return new Promise((resolve, reject) => {
uni.login({
success: function(res) {
resolve(res.code);
},
fail: function(res) {
reject(res);
}
})
})
}// 微信code登录
export function wechatLogin() {
return new Promise((resolve, reject) => {
getCode()
.then((code) => {
// 用code获取用户信息
return onLogin({code})
})
.then((data) => {
// 如果上一次登录的方式为微信登录,则进入小程序可直接用微信code登录
// 若不是说明上次登录为手机号登录或退出登录
const loginType = uni.getStorageSync('loginType')if(!loginType) {
uni.removeStorageSync('WechatUserId')
uni.removeStorageSync('phone')
uni.setStorageSync('registered', false)
} else if(loginType == 'wechat') {
loginCallback(data)
} else {
// 手机号登录(防止因用户删除但是微信缓存中的用户信息未更新)
const userId = uni.getStorageSync('WechatUserId')
if(userId) {
detailUser({id: userId}).then(res => {
loginCallback(res)
})
}
}
// 判断当前微信用户是否注册过
if(data.user) {
uni.setStorageSync('wechatRegistered', true)
uni.setStorageSync('payOpenId', data.openid)
} else {
// 未微信授权的情况下
uni.setStorageSync('wechatRegistered', false)
uni.setStorageSync('payOpenId', data.openid)
}
resolve(data);
})
.catch((err) => {
loginFail(err);
reject(err);
})
})
}export function openSetting() {
return new Promise((resolve) => {
uni.openSetting({
success: function(res) {
resolve(res.authSetting);
}
})
})
}// 根据获取的手机号授权登录
export function cellphoneAuthLogin(code, params = {}) {
return new Promise((resolve, reject) => {
onLogin({code})
.then((data) => {
if(data.sessionId) {
return getPhone({
sessionId: data.sessionId || null,
encryptedData: params.encryptedData || null,
iv: params.iv || null,
})
} else if(data.user) {
return wechatLogin()
}
})
.then((data) => {
if(data.phoneNumber) {
return wechatLogin()
} else if(data.user) {
loginCallback(data);
resolve(data);
}else {
reject(data)
}
})
.then((data) => {
loginCallback(data);
resolve(data);
})
.catch((err) => {
loginFail(err);
reject(err);
})
});
}// 登录成功的回调
export function loginCallback(data) {
const user = data.user || data.response// 获取到用户信息,即为用户注册(登录)成功,触发登录成功的监听事件
listeners.dispatch(events.LOGIN)
if(user) {
uni.setStorageSync('WechatUserId', user.id)
uni.setStorageSync('phone', user.phone)
uni.setStorageSync('registered', true)
} else {
uni.removeStorageSync('WechatUserId')
uni.removeStorageSync('phone')
uni.setStorageSync('registered', false)
}
}export function loginFail(data) {
// console.log(data)
}// 注销登录
export function logOut() {
set(constant.LOGGED_IN, false);
setLogIn(false)
wx.redirectTo({
url: '/pages/login/index'
})
}