UNPKG

mustard-app

Version:

个人前端微应用建设中。。。

157 lines (133 loc) 4.86 kB
import { SandBox } from './proxy/sandBox'; import { loadHtml } from './utils/source'; import { errorLog } from './utils/log'; import { getURL } from './utils'; import { MustardApp } from './element'; import { addInstance, removeInstance } from './global'; import { MustardState, decodeState, initState } from './proxy/proxyHistory'; import { IAppConstructor, IAppStatus, MustardName, MustardURL, SpurceValue } from './typings'; import { EventCenterMicorLife } from './communication'; export default class App { baseUrl: MustardURL; url: MustardURL; name: MustardName; container: MustardApp; sandbox: SandBox; loadCount: number = 0; status = IAppStatus.create; state: MustardState; // document 来源 microLifeCenter: EventCenterMicorLife; // 生命周期通讯 // 存放动态资源 source = { links: new Map<string, SpurceValue>(), // 存放links scripts: new Map<string, SpurceValue>(), // 存放scripts domClick: '\n;' // 存放 dom attrs 上的事件 }; constructor ({ name, url: baseUrl, container }: IAppConstructor) { this.name = name; this.baseUrl = baseUrl; this.container = container; this.microLifeCenter = new EventCenterMicorLife(this.name); this.init(); } // 刷新 卸载->初始化 reload () { this.unmount(true); this.init(); } // 初始化 init () { this.status = IAppStatus.create; this.microLifeCenter.dispatchLife(this.status); // 初始化立刻存入 mustardAppInfos.appInstanceMap addInstance(this.name, this); this.loadCount = 0; // 设置资源的真正地址 this.url = getURL(this.name, this.baseUrl).href; this.source = { links: new Map<string, SpurceValue>(), // 存放links scripts: new Map<string, SpurceValue>(), // 存放scripts domClick: '\n;' // 存放 dom attrs 上的事件 }; // 刷新页面时,为了保证 document.origin 正确,默认取history this.state = decodeState(this.name); if(!this.state) { initState(this.name, '', '', this.url); this.state = decodeState(this.name); } this.status = IAppStatus.loading; this.microLifeCenter.dispatchLife(this.status); // 加载对应的资源 loadHtml(this); // 初始化砂箱 this.sandbox = new SandBox(this.name, this.url); } // 资源加载完时执行 onLoad (htmlDom: HTMLElement) { this.loadCount += 1; // 第二次执行且组件未卸载时执行渲染 if (this.loadCount === 2 && this.status !== IAppStatus.unmount) { // 执行mount方法 this.mount(htmlDom); } } /** * 资源加载完成后进行渲染 */ mount (html: HTMLElement) { this.sandbox.start(); // 克隆DOM节点 const cloneHtml = html.cloneNode(true); // 创建一个fragment节点作为模版,这样不会产生冗余的元素 const fragment = document.createDocumentFragment(); Array.from(cloneHtml.childNodes).forEach((node) => { fragment.appendChild(node); }); // 将格式化后的DOM结构插入到容器中 this.container.appendChild(fragment); // 执行js let scripts = ''; this.source.scripts.forEach((info) => { scripts += info.code + '\n;'; }); { (0, eval)(this.sandbox.bindScope(scripts + '\n;' + this.source.domClick)); } // 标记应用为已渲染 this.status = IAppStatus.mount; this.microLifeCenter.dispatchLife(this.status); } /** * 卸载应用 * 执行关闭沙箱,清空缓存等操作 * @param destory 是否销毁应用 */ unmount (destory: boolean) { this.sandbox.stop(); // 暂停沙箱 this.status = IAppStatus.unmount; this.microLifeCenter.dispatchLife(this.status); if (destory) { this.destory(); } } /** * 销毁应用 */ destory () { this.sandbox = null; this.container.innerHTML = ''; this.status = IAppStatus.destory; this.microLifeCenter.dispatchLife(this.status); removeInstance(this.name); } /** * 子应用加载失败 * @param error 失败原因 */ error (error: Error): void { errorLog(error); this.status = IAppStatus.error; this.microLifeCenter.dispatchLife(this.status); this.microLifeCenter = null; } }