TypeScript + CocosCreator:封装一个可复用的微信用户信息管理模块(WechatManager.ts)
TypeScript CocosCreator构建高可用微信用户信息管理模块在当今移动游戏开发领域微信小游戏因其庞大的用户基础和便捷的社交分享能力已成为开发者不可忽视的平台。然而微信API的复杂性和平台特殊性常常让开发者陷入重复造轮子的困境。本文将带你深入探讨如何用TypeScript在CocosCreator中设计一个工程化、可复用的微信用户信息管理模块解决授权流程、数据缓存、错误处理等核心问题。1. 模块化架构设计原则优秀的模块设计始于清晰的职责划分。我们需要的不是一个简单的API调用封装而是一个具备完整生命周期管理能力的服务层。以下是WechatManager的核心设计目标单一职责仅处理微信相关能力不掺杂UI逻辑状态可追溯完整记录用户授权状态和数据获取情况异常可恢复网络波动、用户拒绝等场景的健壮处理类型安全充分利用TypeScript类型系统避免运行时错误// 基础类型定义 interface IUserInfo { nickName: string avatarUrl: string gender: number country: string province: string city: string } enum AuthStatus { INITIAL, GRANTED, REJECTED, PENDING }2. 核心实现单例模式与状态管理采用改良的单例模式实现既保证全局可访问性又避免过度全局状态。我们引入状态机模式管理授权流程取代传统的回调地狱。2.1 增强型单例实现class WechatManager { private static _instance: WechatManager private _authStatus: AuthStatus AuthStatus.INITIAL private _userInfo: IUserInfo | null null private _authButton: any null // 双重类型断言解决微信API类型问题 private get wx(): typeof wx { return window[wx] as unknown as typeof wx } static get instance(): WechatManager { if (!this._instance) { this._instance new WechatManager() this._instance._setupEnv() } return this._instance } private _setupEnv(): void { if (!this.wx) { console.error(微信环境未初始化) return } // 环境检测逻辑... } }2.2 授权状态机实现状态触发条件后续动作INITIAL首次调用发起权限检查PENDING用户未响应显示授权按钮GRANTED用户同意获取用户信息REJECTED用户拒绝显示重试逻辑async checkAuth(): Promiseboolean { return new Promise((resolve) { this.wx.getSetting({ success: (res) { if (res.authSetting[scope.userInfo]) { this._authStatus AuthStatus.GRANTED this._fetchUserInfo().then(resolve) } else { this._authStatus AuthStatus.PENDING this._createAuthButton() resolve(false) } }, fail: () { this._authStatus AuthStatus.REJECTED resolve(false) } }) }) }3. UI解耦与事件驱动设计传统回调方式会导致UI层与业务逻辑深度耦合。我们采用事件总线模式实现彻底解耦支持多个UI组件同时监听用户数据变化。3.1 事件类型定义// 事件中心实现 import { EventTarget } from cc const EventType { USER_INFO_UPDATE: user-info-update, AUTH_STATUS_CHANGE: auth-status-change } class WechatEventManager { private _eventTarget new EventTarget() emit(type: string, data?: any) { this._eventTarget.emit(type, data) } on(type: string, callback: Function) { this._eventTarget.on(type, callback) } off(type: string, callback?: Function) { this._eventTarget.off(type, callback) } }3.2 UI层消费示例// LoginLayer.ts export class LoginLayer extends Component { onLoad() { WechatManager.event.on(EventType.USER_INFO_UPDATE, this._updateUI.bind(this)) } onDestroy() { WechatManager.event.off(EventType.USER_INFO_UPDATE) } private _updateUI(userInfo: IUserInfo) { this.nameLabel.string userInfo.nickName // 头像加载逻辑... } }4. 高级功能缓存策略与性能优化频繁调用微信API不仅影响用户体验还可能触发接口限流。我们实现多级缓存策略提升性能。4.1 数据缓存实现// 带时效的缓存实现 interface ICacheItemT { data: T expire: number } class DataCache { private static _instance: DataCache private _storage: Recordstring, ICacheItemany {} static get instance(): DataCache { return this._instance || (this._instance new DataCache()) } setT(key: string, data: T, ttl 3600): void { this._storage[key] { data, expire: Date.now() ttl * 1000 } } getT(key: string): T | null { const item this._storage[key] if (!item || item.expire Date.now()) { delete this._storage[key] return null } return item.data as T } }4.2 头像加载优化方案微信头像URL存在跨域限制我们提供两种加载方案本地缓存方案async loadAvatar(url: string): PromiseSpriteFrame { const cacheKey avatar_${md5(url)} const cached DataCache.instance.getImageAsset(cacheKey) if (cached) { return this._createSpriteFrame(cached) } return new Promise((resolve) { assetManager.loadRemoteImageAsset(url, (err, image) { if (!err image) { DataCache.instance.set(cacheKey, image) resolve(this._createSpriteFrame(image)) } }) }) }服务端代理方案解决域名校验问题https://your-server.com/avatar-proxy?urlENCODED_URL5. 工程化实践单元测试与Mock方案健壮的模块需要可测试的设计。我们为微信API创建适配层便于测试环境替换实现。5.1 接口抽象// IWechatService.ts interface IWechatService { getSetting(): PromiseAuthSetting getUserInfo(): PromiseIUserInfo createUserInfoButton(config: ButtonConfig): IButton } // 生产环境实现 class WechatServiceImpl implements IWechatService { // 实际微信API调用... } // 测试环境实现 class MockWechatService implements IWechatService { // 模拟实现... }5.2 测试用例示例describe(WechatManager, () { let manager: WechatManager let mockService: MockWechatService beforeEach(() { mockService new MockWechatService() manager WechatManager.createForTest(mockService) }) it(should handle auth granted, async () { mockService.setAuthStatus(true) const result await manager.checkAuth() expect(result).toBe(true) expect(manager.userInfo).not.toBeNull() }) })6. 生产环境问题排查指南即使设计完善的模块也会遇到环境问题以下是常见问题速查表问题现象可能原因解决方案授权按钮不显示节点层级问题检查zIndex和父节点尺寸头像加载失败域名未配置在微信后台配置downloadFile合法域名getUserInfo返回空数据用户拒绝授权引导用户手动触发授权接口调用频率超限重复调用增加调用间隔和缓存对于头像显示问题除了配置合法域名外还可以使用临时解决方案仅开发环境// 在游戏启动时调用 if (DEBUG) { this.wx.setEnableDebug({ enableDebug: true, success: () { this.wx.startLogManager() } }) }正式环境必须配置的域名https://wx.qlogo.cnhttps://thirdwx.qlogo.cn你的CDN域名7. 扩展思考多平台适配策略虽然本文聚焦微信平台但良好的设计应具备扩展性。我们可以通过策略模式支持多平台// 平台抽象接口 interface IPlatformService { login(): PromiseUserInfo share(content: ShareContent): Promisevoid } // 微信实现 class WechatPlatform implements IPlatformService { // 实现微信特有逻辑 } // 其他平台实现 class WebPlatform implements IPlatformService { // 实现网页版逻辑 } // 上下文选择器 class PlatformContext { static get platform(): IPlatformService { if (env.isWechat) { return new WechatPlatform() } return new WebPlatform() } }这种架构下业务代码只需调用PlatformContext.platform.login()无需关心具体平台实现。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2571046.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!