Open xinre opened 1 year ago
// single-spa.js class SingleSpa { constructor() { this.apps = [] this.currentApp = null } // 注册应用 registerApplication(app) { this.apps.push(app) } // 启动 start() { this.reroute() window.addEventListener('hashchange', () => { this.reroute() }) } // 路由 async reroute() { const { appsToLoad, appsToMount, appsToUnmount } = this.getAppChanges() // 卸载不需要的应用 await Promise.all(appsToUnmount.map(app => this.toUnmountPromise(app))) // 加载需要的应用 appsToLoad.map(async app => { app = await this.toLoadPromise(app) app = await this.toBootstrapPromise(app) return this.toMountPromise(app) }) // 挂载需要的应用 appsToMount.map(async app => { app = await this.toBootstrapPromise(app) return this.toMountPromise(app) }) } // 获取当前应用状态 getAppChanges() { const appsToLoad = [] const appsToMount = [] const appsToUnmount = [] this.apps.forEach(app => { const isActive = app.activeWhen(window.location) switch (app.status) { case 'NOT_LOADED': case 'LOADING_SOURCE_CODE': if (isActive) { appsToLoad.push(app) } break case 'NOT_BOOTSTRAPPED': case 'BOOTSTRAPPING': case 'NOT_MOUNTED': if (isActive) { appsToMount.push(app) } break case 'MOUNTED': if (!isActive) { appsToUnmount.push(app) } break } }) return { appsToLoad, appsToMount, appsToUnmount } } // 加载应用 async toLoadPromise(app) { if (app.status !== 'NOT_LOADED') { return app } app.status = 'LOADING_SOURCE_CODE' let { bootstrap, mount, unmount } = await app.app() app.status = 'NOT_BOOTSTRAPPED' app.bootstrap = bootstrap app.mount = mount app.unmount = unmount return app } // 启动应用 async toBootstrapPromise(app) { if (app.status !== 'NOT_BOOTSTRAPPED') { return app } app.status = 'BOOTSTRAPPING' await app.bootstrap() app.status = 'NOT_MOUNTED' return app } // 挂载应用 async toMountPromise(app) { if (app.status !== 'NOT_MOUNTED') { return app } app.status = 'MOUNTING' await app.mount() app.status = 'MOUNTED' return app } // 卸载应用 async toUnmountPromise(app) { if (app.status !== 'MOUNTED') { return app } app.status = 'UNMOUNTING' await app.unmount() app.status = 'NOT_MOUNTED' return app } } // 导出实例,保证全局只有一个实例(单例模式) export default new SingleSpa()