场景:
在小程序中大家应该都有这样的场景,在onLaunch里用wx.login静默登录拿到code,再用code去发送请求获取token、用户信息等,整个过程都是异步的,然后我们在业务页面里onLoad去用的时候异步请求还没回来,导致没拿到想要的数据,以往要么监听是否拿到,要么自己封装一套回调,总之都挺麻烦,每个页面都要写一堆无关当前页面的逻辑。
直接上终极解决方案,公司内部已接入两年很稳定:
1.可完美解决异步问题
2.不污染原生生命周期,与onLoad等钩子共存
3.使用方便
4.可灵活定制异步钩子
5.采用监听模式实现,接入无需修改以前相关逻辑
6.支持各种小程序和vue架构
。。。
//为了简洁明了的展示使用场景,以下有部分是伪代码,请勿直接粘贴使用,具体使用代码看Github文档
//app.js
//globalData提出来声明
let globalData = {
// 是否已拿到token
token: '',
// 用户信息
userInfo: {
userId: '',
head: ''
}
}
//注册自定义钩子
import CustomHook from 'spa-custom-hooks';
CustomHook.install({
'Login':{
name:'Login',
watchKey: 'token',
onUpdate(token){
//有token则触发此钩子
return !!token;
}
},
'User':{
name:'User',
watchKey: 'userInfo',
onUpdate(user){
//获取到userinfo里的userId则触发此钩子
return !!user.userId;
}
}
}, globalData)
// 正常走初始化逻辑
App({
globalData,
onLaunch() {
//发起异步登录拿token
login((token)=>{
this.globalData.token = token
//使用token拿用户信息
getUser((user)=>{
this.globalData.user = user
})
})
}
})
//关键点来了
//Page.js,业务页面使用
Page({
onLoadLogin() {
//拿到token啦,可以使用token发起请求了
const token = getApp().globalData.token
},
onLoadUser() {
//拿到用户信息啦
const userInfo = getApp().globalData.userInfo
},
onReadyUser() {
//页面初次渲染完毕 && 拿到用户信息,可以把头像渲染在canvas上面啦
const userInfo = getApp().globalData.userInfo
// 获取canvas上下文
const ctx = getCanvasContext2d()
ctx.drawImage(userInfo.head,0,0,100,100)
},
onShowUser() {
//页面每次显示 && 拿到用户信息,我要在页面每次显示的时候根据userInfo走不同的逻辑
const userInfo = getApp().globalData.userInfo
switch(userInfo.sex){
case 0:
// 走女生逻辑
break
case 1:
// 走男生逻辑
break
}
}
})
具体文档和Demo见↓
Github:https://github.com/1977474741/spa-custom-hooks
祝大家用的愉快,记得star哦
分享一下我碰到的问题;已解决
我的问题是第一次编译的时候,userInfo对象数据更新,无法触发Page页面onLoadXX(XX代表监听函数的名字),第二次确可以。
我的猜想说一下,首先这个钩子函数应该是通过object.defineProperty进行监听对象的。当通过直接赋值的形式操作时(改变源对象的内存地址),那么钩子函数就监听不到了,所以就导致我这边onLoadXX(XX代表监听函数的名字)执行不了。下面是一个简单的demo
let number = 20; let obj = {a:1}; let obj1 = {a:2}; Object.defineProperty(obj,"b",{ get(){ console.log("有人读取了b属性") return number }, set(val){ number = val } }) obj = obj1; obj.b = 30; console.log(obj,number);// {a:2,b:30} (不再是响应式了) number=>20
改善方法
obj = obj1; //改为对对象进行合并,保留源对象的内存地址 obj = Object.assign(obj,obj1); obj.b = 30; console.log(obj,number);// {a:2,b:30} (不再是响应式了) number=>30
希望大家碰到这个问题能快速解决,反正我花了不少时间解决这个问题。如果条件有限的 作者可以加个判断,判断当前对象内存地址是否已经变化,然后告诉开发者。
uniapp用不起来嘛
钉钉小程序调用为啥报错不能使用吗![](http://mmbiz.qpic.cn/sz_mmbiz_png/8a8PeiaNia6oohXrgOxZmhjMS21IGrVIr6scNL5hK7FavACBiaHMaCAUO1XfknF1iccHLsr59O11z4M63OTac2YNXQ/0?wx_fmt=png)
大哥,请问在vue3中怎么使用该钩子函数?
我试了,在微信开发工具上,切换页面时Page下的onShowLogin有时候执行不了,偶发性的,这是什么问题。
直接上代码
// util.js let onLaunchedCallback const onLaunchedPromise = new Promise(resolve => { onLaunchedCallback = resolve }) // App调用 export const setLaunched = success => onLaunchedCallback(success) // 页面调用 export const onLaunched = () => onLaunchedPromise // App.vue import { setLaunched } from "./util.js" export default { async onLaunch() { // 发起登录请求 let success = await this.login() // 登录成功后调用回调(通知promise resolve) setLaunched(success) }, methods: { async login() { // ...省略登录逻辑代码 return true }, }, } // page import { onLaunched } from "./util.js" export default { name: "HomePage", async onLoad() { await onLaunched() // this.fetchData() }, }
onLoginAttached
这个不生效呀
看起来不错 用下试试
vue3+uniapp项目中怎么使用
请问uniapp怎样用这个方案