Optimize Modular
This commit is contained in:
parent
49ed8e588a
commit
121b620312
@ -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<T = unknown> = (event: T) => void;
|
||||
export type WildcardHandler<T = Record<string, unknown>> = (
|
||||
type: keyof T,
|
||||
event: T[keyof T]
|
||||
) => void;
|
||||
export type Handler<T = any> = (event: T) => void;
|
||||
|
||||
// An array of all currently registered event handlers for a type
|
||||
export type EventHandlerList<T = unknown> = Array<Handler<T>>;
|
||||
export type WildCardEventHandlerList<T = Record<string, unknown>> = Array<WildcardHandler<T>>;
|
||||
export type EventHandlerList<T = any> = Array<Handler<T>>;
|
||||
|
||||
// A map of event types and their corresponding event handlers.
|
||||
export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
|
||||
keyof Events | '*',
|
||||
EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>
|
||||
export type EventHandlerMap<Events extends Record<EventType, any>> = Map<
|
||||
keyof Events,
|
||||
EventHandlerList<Events[keyof Events]>
|
||||
>;
|
||||
|
||||
type GenericEventHandler<Events extends Record<EventType, unknown>> =
|
||||
| Handler<Events[keyof Events]>
|
||||
| WildcardHandler<Events>;
|
||||
|
||||
export class Emitter<Events extends Record<EventType, unknown>> {
|
||||
export class Emitter<Events extends Record<EventType, any>> {
|
||||
|
||||
/**
|
||||
* A Map of event names to registered handler functions.
|
||||
@ -41,17 +32,14 @@ export class Emitter<Events extends Record<EventType, unknown>> {
|
||||
this.all!.set(type, [] as EventHandlerList<Events[keyof Events]>);
|
||||
}
|
||||
|
||||
on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
|
||||
on(type: '*', handler: WildcardHandler<Events>): 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<Key extends keyof Events>(type: Key, handler: GenericEventHandler<Events>) {
|
||||
const handlers: Array<GenericEventHandler<Events>> | undefined = this.all!.get(type);
|
||||
public on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>) {
|
||||
const handlers: Array<Handler<Events[Key]>> | undefined = this.all!.get(type);
|
||||
if (handlers) {
|
||||
handlers.push(handler);
|
||||
}
|
||||
@ -60,18 +48,15 @@ export class Emitter<Events extends Record<EventType, unknown>> {
|
||||
}
|
||||
}
|
||||
|
||||
off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
|
||||
off(type: '*', handler: WildcardHandler<Events>): 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<Key extends keyof Events>(type: Key, handler?: GenericEventHandler<Events>) {
|
||||
const handlers: Array<GenericEventHandler<Events>> | undefined = this.all!.get(type);
|
||||
public off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>) {
|
||||
const handlers: Array<Handler<Events[Key]>> | undefined = this.all!.get(type);
|
||||
if (handlers) {
|
||||
if (handler) {
|
||||
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
|
||||
@ -82,20 +67,14 @@ export class Emitter<Events extends Record<EventType, unknown>> {
|
||||
}
|
||||
}
|
||||
|
||||
emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
|
||||
emit<Key extends keyof Events>(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<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
|
||||
emit<Key extends keyof Events>(type: Key, evt: Events[Key]) {
|
||||
let handlers = this.all!.get(type);
|
||||
if (handlers) {
|
||||
(handlers as EventHandlerList<Events[keyof Events]>)
|
||||
@ -104,14 +83,5 @@ export class Emitter<Events extends Record<EventType, unknown>> {
|
||||
handler(evt!);
|
||||
});
|
||||
}
|
||||
|
||||
handlers = this.all!.get('*');
|
||||
if (handlers) {
|
||||
(handlers as WildCardEventHandlerList<Events>)
|
||||
.slice()
|
||||
.map((handler) => {
|
||||
handler(type, evt!);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -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<M extends Manager<AnyWXContext>> = {
|
||||
[x:string]: Modular<M, Depends<M>>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 微信继承的函数
|
||||
*/
|
||||
class WXInstanceMethods<
|
||||
E extends IAnyTypeObject = IAnyTypeObject,
|
||||
W extends AnyWXContext = AnyWXContext
|
||||
>
|
||||
extends Emitter<E>
|
||||
implements InstanceMethods<W["data"]> {
|
||||
|
||||
public superContext: W;
|
||||
|
||||
public constructor(context: W) {
|
||||
super();
|
||||
this.superContext = context;
|
||||
}
|
||||
|
||||
public setData(data: Partial<W["data"]> & WechatMiniprogram.IAnyObject, callback?: () => void): void {
|
||||
return this.superContext.setData(data, callback);
|
||||
}
|
||||
|
||||
public hasBehavior(behavior: string): void {
|
||||
return this.superContext.hasBehavior(behavior);
|
||||
}
|
||||
|
||||
public triggerEvent<DetailType = any>(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<E, W>
|
||||
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<string, string | undefined> { return this.superContext.options };
|
||||
}
|
||||
|
||||
class WXILifetime<
|
||||
E extends IAnyTypeObject = IAnyTypeObject,
|
||||
W extends AnyWXContext = AnyWXContext
|
||||
>
|
||||
extends WXInstanceProperties<E, W>
|
||||
implements ILifetime {
|
||||
|
||||
public onLoad(query: Record<string, string | undefined>): void | Promise<void> {};
|
||||
|
||||
public onShow(): void | Promise<void> {};
|
||||
|
||||
public onReady(): void | Promise<void> {};
|
||||
|
||||
public onHide(): void | Promise<void> {};
|
||||
|
||||
public onUnload(): void | Promise<void> {};
|
||||
|
||||
public onPullDownRefresh(): void | Promise<void> {};
|
||||
|
||||
public onReachBottom(): void | Promise<void> {};
|
||||
|
||||
public onShareAppMessage(options: WechatMiniprogram.Page.IShareAppMessageOption): void | WechatMiniprogram.Page.ICustomShareContent {};
|
||||
|
||||
public onShareTimeline(): void | WechatMiniprogram.Page.ICustomTimelineContent {};
|
||||
|
||||
public onPageScroll(options: WechatMiniprogram.Page.IPageScrollOption): void | Promise<void> {};
|
||||
|
||||
public onTabItemTap(options: WechatMiniprogram.Page.ITabItemTapOption): void | Promise<void> {};
|
||||
|
||||
public onResize(options: WechatMiniprogram.Page.IResizeOption): void | Promise<void> {};
|
||||
|
||||
public onAddToFavorites(options: WechatMiniprogram.Page.IAddToFavoritesOption): WechatMiniprogram.Page.IAddToFavoritesContent {
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面模组
|
||||
* @template M 所属 Manager
|
||||
@ -60,9 +203,10 @@ type Depends<M extends Manager<AnyWXContext>> = {
|
||||
class Modular<
|
||||
M extends Manager<AnyWXContext> = Manager<AnyWXContext>,
|
||||
DEP extends Depends<M> = Depends<M>,
|
||||
E extends Record<EventType, unknown> = Record<EventType, unknown>,
|
||||
TD extends IAnyTypeObject = IAnyTypeObject>
|
||||
extends Emitter<E>
|
||||
E extends IAnyTypeObject = IAnyTypeObject,
|
||||
TD extends IAnyTypeObject = IAnyTypeObject
|
||||
>
|
||||
extends WXILifetime<E, M["context"]>
|
||||
implements WXContext<TD, IAnyTypeObject> {
|
||||
|
||||
// [x:string]: any;
|
||||
@ -95,7 +239,7 @@ implements WXContext<TD, IAnyTypeObject> {
|
||||
public functionList:Set<string>;
|
||||
|
||||
/**
|
||||
* 函数使用的参数列表
|
||||
* 模组使用的参数列表
|
||||
*/
|
||||
public paramList:Set<string>;
|
||||
|
||||
@ -103,13 +247,6 @@ implements WXContext<TD, IAnyTypeObject> {
|
||||
* 命名空间
|
||||
*/
|
||||
public nameSpace:string;
|
||||
|
||||
// 映射主上下文属性
|
||||
public get is():string { return this.context.is };
|
||||
public get route():string { return this.context.route };
|
||||
public get options():Record<string, string | undefined> {
|
||||
return this.context.options;
|
||||
};
|
||||
|
||||
/**
|
||||
* 一旦被类被构造,整个页面的全部申明周期将
|
||||
@ -120,7 +257,7 @@ implements WXContext<TD, IAnyTypeObject> {
|
||||
*/
|
||||
public constructor(manager:M, nameSpace:string, depend?: DEP) {
|
||||
|
||||
super();
|
||||
super(manager.context);
|
||||
|
||||
// 保存微信上下文
|
||||
this.manager = manager;
|
||||
@ -134,7 +271,7 @@ implements WXContext<TD, IAnyTypeObject> {
|
||||
this.nameSpace = nameSpace;
|
||||
}
|
||||
|
||||
public setData(data:Partial<TD>, callback?: () => void):void {
|
||||
public override setData(data:Partial<TD>, callback?: () => void):void {
|
||||
|
||||
if(this.data === void 0) {
|
||||
this.data = {} as TD;
|
||||
@ -162,76 +299,6 @@ implements WXContext<TD, IAnyTypeObject> {
|
||||
(this.context as IAnyTypeObject)
|
||||
[`${ this.nameSpace }$${ name }`] = fn.bind(this);
|
||||
}
|
||||
|
||||
//#region 映射微信的继承函数
|
||||
|
||||
public hasBehavior(behavior: string): void {
|
||||
return this.context.hasBehavior(behavior);
|
||||
}
|
||||
|
||||
public triggerEvent<DetailType>(name: string, detail?: DetailType,
|
||||
options?: WechatMiniprogram.Component.TriggerEventOption): void {
|
||||
return this.context.triggerEvent<DetailType>(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<WXC extends AnyWXContext = AnyWXContext> {
|
||||
* 微信生命周期
|
||||
*/
|
||||
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<WXC extends AnyWXContext = AnyWXContext> {
|
||||
* @param depend 模块依赖
|
||||
* @returns 模块实例
|
||||
*/
|
||||
public addModule<DEP extends Depends<this>, M extends Modular<this, DEP>>
|
||||
(mode: new (manager:Manager<WXC>, nameSpace:string, depend?:DEP) => M,
|
||||
nameSpace:string, depend?:DEP):M {
|
||||
public addModule<DEP extends Depends<this>, M extends Modular<this, DEP>> (
|
||||
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<WXC extends AnyWXContext = AnyWXContext> {
|
||||
* 创建指定生命周期的钩子
|
||||
* @param key 生命周期键值
|
||||
*/
|
||||
public creatHooks(key:keyof ILifetime):(...arg: any[]) => Promise<any> {
|
||||
return async (...arg: any[]) => {
|
||||
public creatHooks<Key extends keyof ILifetime>(key: Key): ILifetime[Key] {
|
||||
let hook = (async (...arg: any[]) => {
|
||||
|
||||
let hooks:Promise<any>[] = [];
|
||||
|
||||
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> | any = fn.apply(this.modules[i], arg);
|
||||
@ -340,7 +398,10 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
|
||||
}
|
||||
|
||||
return Promise.all(hooks);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: 此处为,关键位置,容易出错,请再次检查
|
||||
return (hook as any);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,7 +444,7 @@ class Manager<WXC extends AnyWXContext = AnyWXContext> {
|
||||
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<WXC extends AnyWXContext = AnyWXContext> {
|
||||
/**
|
||||
* 模块被添加时的标签
|
||||
*/
|
||||
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)
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,7 @@ import { Storage } from "../../core/Storage";
|
||||
class TestCore<M extends Manager> extends Modular<M>
|
||||
implements Partial<ILifetime> {
|
||||
|
||||
public onLoad() {
|
||||
public override onLoad() {
|
||||
|
||||
let s = new Storage("test", {
|
||||
a: new Date(),
|
||||
|
Loading…
Reference in New Issue
Block a user