diff --git a/miniprogram/core/Emitter.ts b/miniprogram/core/Emitter.ts index 06ca652..bc237e1 100644 --- a/miniprogram/core/Emitter.ts +++ b/miniprogram/core/Emitter.ts @@ -2,27 +2,18 @@ export type EventType = string | symbol; // An event handler can take an optional event argument // and should not return a value -export type Handler = (event: T) => void; -export type WildcardHandler> = ( - type: keyof T, - event: T[keyof T] -) => void; +export type Handler = (event: T) => void; // An array of all currently registered event handlers for a type -export type EventHandlerList = Array>; -export type WildCardEventHandlerList> = Array>; +export type EventHandlerList = Array>; // A map of event types and their corresponding event handlers. -export type EventHandlerMap> = Map< - keyof Events | '*', - EventHandlerList | WildCardEventHandlerList +export type EventHandlerMap> = Map< + keyof Events, + EventHandlerList >; -type GenericEventHandler> = - | Handler - | WildcardHandler; - -export class Emitter> { +export class Emitter> { /** * A Map of event names to registered handler functions. @@ -41,17 +32,14 @@ export class Emitter> { this.all!.set(type, [] as EventHandlerList); } - on(type: Key, handler: Handler): void; - on(type: '*', handler: WildcardHandler): void; - /** * Register an event handler for the given type. - * @param {string|symbol} type Type of event to listen for, or `'*'` for all events + * @param {string|symbol} type Type of event to listen for * @param {Function} handler Function to call in response to given event * @memberOf mitt */ - public on(type: Key, handler: GenericEventHandler) { - const handlers: Array> | undefined = this.all!.get(type); + public on(type: Key, handler: Handler) { + const handlers: Array> | undefined = this.all!.get(type); if (handlers) { handlers.push(handler); } @@ -60,18 +48,15 @@ export class Emitter> { } } - off(type: Key, handler?: Handler): void; - off(type: '*', handler: WildcardHandler): void; - /** * Remove an event handler for the given type. * If `handler` is omitted, all handlers of the given type are removed. - * @param {string|symbol} type Type of event to unregister `handler` from, or `'*'` + * @param {string|symbol} type Type of event to unregister `handler` from * @param {Function} [handler] Handler function to remove * @memberOf mitt */ - public off(type: Key, handler?: GenericEventHandler) { - const handlers: Array> | undefined = this.all!.get(type); + public off(type: Key, handler?: Handler) { + const handlers: Array> | undefined = this.all!.get(type); if (handlers) { if (handler) { handlers.splice(handlers.indexOf(handler) >>> 0, 1); @@ -82,20 +67,14 @@ export class Emitter> { } } - emit(type: Key, event: Events[Key]): void; - emit(type: undefined extends Events[Key] ? Key : never): void; - /** * Invoke all handlers for the given type. - * If present, `'*'` handlers are invoked after type-matched handlers. - * - * Note: Manually firing '*' handlers is not supported. * * @param {string|symbol} type The event type to invoke * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler * @memberOf mitt */ - emit(type: Key, evt?: Events[Key]) { + emit(type: Key, evt: Events[Key]) { let handlers = this.all!.get(type); if (handlers) { (handlers as EventHandlerList) @@ -104,14 +83,5 @@ export class Emitter> { handler(evt!); }); } - - handlers = this.all!.get('*'); - if (handlers) { - (handlers as WildCardEventHandlerList) - .slice() - .map((handler) => { - handler(type, evt!); - }); - } } } \ No newline at end of file diff --git a/miniprogram/core/Module.ts b/miniprogram/core/Module.ts index 61610ce..5a5c559 100644 --- a/miniprogram/core/Module.ts +++ b/miniprogram/core/Module.ts @@ -1,5 +1,5 @@ -import { Emitter, EventType } from "./Emitter"; -import { Logger, LogLabel, LogStyle, LevelLogLabel } from "./Logger"; +import { Emitter } from "./Emitter"; +import { Logger, LogLabel, colorRadio, LevelLogLabel } from "./Logger"; /** * 自定义对象类型 @@ -50,6 +50,149 @@ type Depends> = { [x:string]: Modular>; }; +/** + * 微信继承的函数 + */ +class WXInstanceMethods< + E extends IAnyTypeObject = IAnyTypeObject, + W extends AnyWXContext = AnyWXContext +> +extends Emitter +implements InstanceMethods { + + public superContext: W; + + public constructor(context: W) { + super(); + this.superContext = context; + } + + public setData(data: Partial & WechatMiniprogram.IAnyObject, callback?: () => void): void { + return this.superContext.setData(data, callback); + } + + public hasBehavior(behavior: string): void { + return this.superContext.hasBehavior(behavior); + } + + public triggerEvent(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption): void { + return this.superContext.triggerEvent(name, detail, options) + } + + public createSelectorQuery(): WechatMiniprogram.SelectorQuery { + return this.superContext.createSelectorQuery(); + } + + public createIntersectionObserver(options: WechatMiniprogram.CreateIntersectionObserverOption): WechatMiniprogram.IntersectionObserver { + return this.superContext.createIntersectionObserver(options); + } + + public selectComponent(selector: string): WechatMiniprogram.Component.TrivialInstance { + return this.superContext.selectComponent(selector); + } + + public selectAllComponents(selector: string): WechatMiniprogram.Component.TrivialInstance[] { + return this.superContext.selectAllComponents(selector); + } + + public selectOwnerComponent(): WechatMiniprogram.Component.TrivialInstance { + return this.superContext.selectOwnerComponent(); + } + + public getRelationNodes(relationKey: string): WechatMiniprogram.Component.TrivialInstance[] { + return this.superContext.getRelationNodes(relationKey); + } + + public groupSetData(callback?: () => void): void { + return this.superContext.groupSetData(callback); + } + + public getTabBar(): WechatMiniprogram.Component.TrivialInstance { + return this.superContext.getTabBar(); + } + + public getPageId(): string { + return this.superContext.getPageId(); + } + + public animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[], duration: number, callback?: () => void): void; + public animate(selector: string, keyFrames: WechatMiniprogram.Component.ScrollTimelineKeyframe[], duration: number, + scrollTimeline: WechatMiniprogram.Component.ScrollTimelineOption): void; + public animate(selector: any, keyFrames: any, duration: any, scrollTimeline?: any): void { + return this.superContext.animate(selector, keyFrames, duration, scrollTimeline); + } + + public clearAnimation(selector: string, callback: () => void): void; + public clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions, callback?: () => void): void; + public clearAnimation(selector: any, options?: any, callback?: any): void { + return this.superContext.clearAnimation(selector, options, callback); + } + + public getOpenerEventChannel(): WechatMiniprogram.EventChannel { + return this.superContext.getOpenerEventChannel(); + } +} + +/** + * 微信继承的属性 + */ +class WXInstanceProperties< + E extends IAnyTypeObject = IAnyTypeObject, + W extends AnyWXContext = AnyWXContext +> +extends WXInstanceMethods +implements InstanceProperties { + + public override superContext: W; + + constructor(context: W) { + super(context); + this.superContext = context; + } + + public get is(): string { return this.superContext.is }; + + public get route(): string { return this.superContext.route }; + + public get options(): Record { return this.superContext.options }; +} + +class WXILifetime< + E extends IAnyTypeObject = IAnyTypeObject, + W extends AnyWXContext = AnyWXContext +> +extends WXInstanceProperties +implements ILifetime { + + public onLoad(query: Record): void | Promise {}; + + public onShow(): void | Promise {}; + + public onReady(): void | Promise {}; + + public onHide(): void | Promise {}; + + public onUnload(): void | Promise {}; + + public onPullDownRefresh(): void | Promise {}; + + public onReachBottom(): void | Promise {}; + + public onShareAppMessage(options: WechatMiniprogram.Page.IShareAppMessageOption): void | WechatMiniprogram.Page.ICustomShareContent {}; + + public onShareTimeline(): void | WechatMiniprogram.Page.ICustomTimelineContent {}; + + public onPageScroll(options: WechatMiniprogram.Page.IPageScrollOption): void | Promise {}; + + public onTabItemTap(options: WechatMiniprogram.Page.ITabItemTapOption): void | Promise {}; + + public onResize(options: WechatMiniprogram.Page.IResizeOption): void | Promise {}; + + public onAddToFavorites(options: WechatMiniprogram.Page.IAddToFavoritesOption): WechatMiniprogram.Page.IAddToFavoritesContent { + return {}; + }; +} + /** * 页面模组 * @template M 所属 Manager @@ -60,9 +203,10 @@ type Depends> = { class Modular< M extends Manager = Manager, DEP extends Depends = Depends, - E extends Record = Record, - TD extends IAnyTypeObject = IAnyTypeObject> -extends Emitter + E extends IAnyTypeObject = IAnyTypeObject, + TD extends IAnyTypeObject = IAnyTypeObject +> +extends WXILifetime implements WXContext { // [x:string]: any; @@ -95,7 +239,7 @@ implements WXContext { public functionList:Set; /** - * 函数使用的参数列表 + * 模组使用的参数列表 */ public paramList:Set; @@ -103,13 +247,6 @@ implements WXContext { * 命名空间 */ public nameSpace:string; - - // 映射主上下文属性 - public get is():string { return this.context.is }; - public get route():string { return this.context.route }; - public get options():Record { - return this.context.options; - }; /** * 一旦被类被构造,整个页面的全部申明周期将 @@ -120,7 +257,7 @@ implements WXContext { */ public constructor(manager:M, nameSpace:string, depend?: DEP) { - super(); + super(manager.context); // 保存微信上下文 this.manager = manager; @@ -134,7 +271,7 @@ implements WXContext { this.nameSpace = nameSpace; } - public setData(data:Partial, callback?: () => void):void { + public override setData(data:Partial, callback?: () => void):void { if(this.data === void 0) { this.data = {} as TD; @@ -162,76 +299,6 @@ implements WXContext { (this.context as IAnyTypeObject) [`${ this.nameSpace }$${ name }`] = fn.bind(this); } - - //#region 映射微信的继承函数 - - public hasBehavior(behavior: string): void { - return this.context.hasBehavior(behavior); - } - - public triggerEvent(name: string, detail?: DetailType, - options?: WechatMiniprogram.Component.TriggerEventOption): void { - return this.context.triggerEvent(name, detail, options); - } - - public createSelectorQuery(): WechatMiniprogram.SelectorQuery { - return this.context.createSelectorQuery(); - } - - public createIntersectionObserver(options: WechatMiniprogram.CreateIntersectionObserverOption): - WechatMiniprogram.IntersectionObserver { - return this.context.createIntersectionObserver(options); - } - - public selectComponent(selector: string): WechatMiniprogram.Component.TrivialInstance { - return this.context.selectComponent(selector); - } - - public selectAllComponents(selector: string): WechatMiniprogram.Component.TrivialInstance[] { - return this.context.selectAllComponents(selector); - } - - public selectOwnerComponent(): WechatMiniprogram.Component.TrivialInstance { - return this.context.selectOwnerComponent(); - } - - public getRelationNodes(relationKey: string): WechatMiniprogram.Component.TrivialInstance[] { - return this.context.getRelationNodes(relationKey); - } - - public groupSetData(callback?: () => void): void { - return this.context.groupSetData(callback); - } - - public getTabBar(): WechatMiniprogram.Component.TrivialInstance { - return this.context.getTabBar(); - } - - public getPageId(): string { - return this.context.getPageId(); - } - - public animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[], - duration: number, callback?: () => void): void; - public animate(selector: string, keyFrames: WechatMiniprogram.Component.ScrollTimelineKeyframe[], - duration: number, scrollTimeline: WechatMiniprogram.Component.ScrollTimelineOption): void; - public animate(selector: any, keyFrames: any, duration: any, scrollTimeline?: any): void { - return this.context.animate(selector, keyFrames, duration, scrollTimeline); - } - - public clearAnimation(selector: string, callback: () => void): void; - public clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions, - callback?: () => void): void; - public clearAnimation(selector: any, options?: any, callback?: any): void { - return this.context.clearAnimation(selector, options, callback); - } - - public getOpenerEventChannel(): WechatMiniprogram.EventChannel { - return this.context.getOpenerEventChannel(); - } - - //#endregion - } /** @@ -244,19 +311,9 @@ class Manager { * 微信生命周期 */ static readonly WxLifeCycle:(keyof ILifetime)[] = [ - "onShow", - "onReady", - "onHide", - "onUnload", - "onPullDownRefresh", - "onReachBottom", - "onShareAppMessage", - "onShareTimeline", - "onAddToFavorites", - "onPageScroll", - "onResize", - "onTabItemTap" - ] + "onShow", "onReady", "onHide", "onUnload", "onPullDownRefresh", "onReachBottom", + "onShareAppMessage", "onShareTimeline","onAddToFavorites","onPageScroll", "onResize", "onTabItemTap" + ]; /** * 保存页面上下文 @@ -288,9 +345,10 @@ class Manager { * @param depend 模块依赖 * @returns 模块实例 */ - public addModule, M extends Modular> - (mode: new (manager:Manager, nameSpace:string, depend?:DEP) => M, - nameSpace:string, depend?:DEP):M { + public addModule, M extends Modular> ( + mode: new (manager:this, nameSpace:string, depend?:DEP) => M, + nameSpace:string, depend?:DEP + ):M { let mod = new mode(this, nameSpace, depend); this.modules.push(mod); return mod; @@ -300,14 +358,14 @@ class Manager { * 创建指定生命周期的钩子 * @param key 生命周期键值 */ - public creatHooks(key:keyof ILifetime):(...arg: any[]) => Promise { - return async (...arg: any[]) => { + public creatHooks(key: Key): ILifetime[Key] { + let hook = (async (...arg: any[]) => { let hooks:Promise[] = []; for(let i = 0; i < this.modules.length; i++) { - let fn:Function = (this.modules[i] as IAnyTypeObject)[key]; + let fn:Function = this.modules[i][key]; if(fn === void 0) continue; let res: Promise | any = fn.apply(this.modules[i], arg); @@ -340,7 +398,10 @@ class Manager { } return Promise.all(hooks); - } + }); + + // TODO: 此处为,关键位置,容易出错,请再次检查 + return (hook as any); } /** @@ -383,7 +444,7 @@ class Manager { this.context.setData(this.context.data); // 调用全部模块的 onLoad 周期 - let res = this.creatHooks("onLoad")(query as any); + let res = this.creatHooks("onLoad")(query); // 打印每个模块的键值对使用情况 for(let i = 0; i < this.modules.length; i++) { @@ -411,9 +472,9 @@ class Manager { /** * 模块被添加时的标签 */ - public static readonly AddModuleLabel = new LogLabel("addModule", - new LogStyle().setBorder("4px", `1px solid #8600FF`) - .setColor("#FF00FF", "rgba(54, 0, 255, .2)").setBlank("0 5px") + public static readonly AddModuleLabel = new LogLabel( + "addModule", + colorRadio(54, 0, 255) ) /** diff --git a/miniprogram/pages/Timetable/StatusBar.ts b/miniprogram/pages/Timetable/StatusBar.ts index d248d9a..41aa963 100644 --- a/miniprogram/pages/Timetable/StatusBar.ts +++ b/miniprogram/pages/Timetable/StatusBar.ts @@ -4,7 +4,7 @@ import { Logger, LogLabel, LevelLogLabel, LifeCycleLogLabel, NormalStyle } from /** * 在 UI 中显示的数据 */ -type DisplayData = { +interface IDisplayData { /** * 显示内容 @@ -20,8 +20,8 @@ type DisplayData = { /** * 模组事件 */ -type StatusBarEvent = { - m: DisplayData +interface StatusBarEvent { + m: IDisplayData }; /** diff --git a/miniprogram/pages/Timetable/TestCore.ts b/miniprogram/pages/Timetable/TestCore.ts index 2fc8e6c..cc9c7cd 100644 --- a/miniprogram/pages/Timetable/TestCore.ts +++ b/miniprogram/pages/Timetable/TestCore.ts @@ -8,7 +8,7 @@ import { Storage } from "../../core/Storage"; class TestCore extends Modular implements Partial { - public onLoad() { + public override onLoad() { let s = new Storage("test", { a: new Date(),