import { Options, HookType } from "../types/page"; import * as Component from "../types/component"; import defineReactive from "../common/define-reactive"; import BaseComponentRender from "../component/BaseComponentRender"; import factory from "../common/factory"; import Context from "../common/context"; import EventEmitter from "../common/event-emitter"; import { LOADED } from "../constant/context"; export { factory }; export default class BasePageRender extends EventEmitter { // 当前页面的状态 public $status: HookType = HookType.beforeCreate; public $el: HTMLElement; public $context: Context; // 页面参数 public $options: Options; public $children: Array = []; /** * 导出配置 */ public exportJson: () => Options; constructor(el: HTMLElement, options: Options, context: Context) { super(); this.$el = el; this.$context = context; this.$options = this.defineReactive(options); this.create(); this.exportJson = () => { return options; }; } /** * 构建页面 */ private create() { this.invokeHook(HookType.beforeMount); let promiseList: Array> = []; this.$context.once(LOADED, (uid: string, percent: number) => { this.invokeHook(HookType.mounted); }); // 依次构建内部组件 (this.$options.components || []).forEach((options: Component.Options, index: number) => { promiseList.push(factory.createComponent(this.$context, options, this, index)); }); Promise.all(promiseList); } /** * 触发当前页面的生命周期 * @param type */ protected invokeHook(type: HookType) { this.$status = type; if (type in this && typeof (this as any)[type] === "function") { (this as any)[type].call(this); } } /** * 触发自定义扩展组件的事件 * @param type * @param params */ protected invokeEvent(type: string, ...params: any[]) { // TODO: 执行component.events 下的方法 } /** * 设置响应式参数 * @param options */ protected defineReactive(options: Options) { return defineReactive(options, { set: () => { // this.reload(); console.log("TODO: Reactive"); } }); } /** * 重新渲染 */ public rerender(options: Options) { // TODO: 需进行 diff 算法 // 触发所有节点的删除逻辑 this.$children.forEach((child: BaseComponentRender) => { child.remove(); }); this.$children = []; // 重新对options进行响应式处理 this.$options = this.defineReactive(options); // 依次构建内部组件 (this.$options.components || []).forEach((options: Component.Options, index: number) => { factory.createComponent(this.$context, options, this, index); }); } /** * 卸载当前页面 */ public remove(): void { this.invokeHook(HookType.beforeDestroy); this.removeAllListener(); // 触发所有节点的删除逻辑 this.$children.forEach((child) => { child.remove(); }); this.invokeHook(HookType.destroyed); if (this.$el) { this.$el.innerHTML = ""; } } /** * 添加子节点 * @param component * @param index */ public insertBefore(component: BaseComponentRender, index?: number) { index = index || 0; if (index > this.$children.length - 1) { this.$children.push(component); this.$el && this.$el.appendChild(component.$el as HTMLElement); } else { this.$el && this.$el.insertBefore(component.$el as HTMLElement, this.$children[index].$el!); this.$children.splice(index, 0, component); } } public size() { return this.$children.length; } }