设置环境变量
- 我们完成了子应用页面的显示,但是由于我们之前设置的
window.__MICRO_WEB__从来没有改变过,进入子应用时,会重复进行渲染,我们可以看下子应用设置的逻辑 ```javascript function render() { instance = createApp(App); instance .use(router) .mount(‘#app’); } // 一直会执行到这里面 if (!window.MICRO_WEB) { render(); } export async function bootstrap() { console.log(‘vue3.0 app bootstrap’); }
export async function mount(app) { setMain(app) render(); }
export async function unmount(ctx) { instance.unmount(); instance = null; const { container } = ctx if (container) { document.querySelector(container).innerHTML = ‘’ } }
- 除了一直执行`render`方法,子应用的声明周期我们也没有出发到,所以我们要在加载子应用页面的时候,设置`__MICRO_WEB__`为`true````javascriptexport const loadHtml = async (app) => {window.__MICRO_WEB__ = true;}
我们设置
__MICRO_WEB__为true后,子应用不再调用render方法,需要执行mount声明周期来触发执行render,我们需要处理我们子应用声明周期的执行获取子应用生命周期
我们通过执行js脚本,来获取到子应用声明周期
main\micro\sandbox\index.js
// 2. 运行js文件,获取子应用生命周期// const lifeCycle = performScript(script, app.name);const lifeCycle = performScriptForEval(script, app.name);console.log('lifeCycle', lifeCycle);
performScriptForEval执行内容
const scriptText =`() => {${script}return window[${appName}]}`;return eval(scriptText);

我们获取到的内容是js脚本文件,并不是我们想要的module,这是因为当前返回的window,并不是我们的window对象
我们通过call,将指针指向window,并传入window参数
const scriptText =`() => {${script}return window[${appName}]}`;return eval(scriptText).call(window,window);
上面这种方式执行的时候获取不到子应用全局变量,具体原因没找到
- 最终写法都可以获取到子应用声明周期
``javascript // 执行应用的 js 内容 new Function 篇 export const performScript = (script, appName) => { const scriptText =${script} return window[${appName}] ` return new Function(scriptText).call(window, window);
}
// 执行应用中的 js 内容 eval篇
export const performScriptForEval = (script, appName) => {
// 我们在子应用打包配置中设置了library,全局变量名
// 我们通过执行window.appName 来获取子应用声明周期
const scriptText = (() => () => {
try {
${script}
return window['${appName}']
} catch (err) {
console.error('runScript error:' + err);
}
})()
return (() => eval(scriptText))().call(window, window);
}
<a name="WkbwX"></a># 将声明周期挂载到app上```javascript// 判断是否有生命周期function isCheckLiftCycle(lifeCycle) {return lifeCycle && lifeCycle.bootstrap && lifeCycle.mount && lifeCycle.unmount;}// 将子应用生命周期挂载到app上// beforeLoaded 生命周期执行完之后,我们挂载了子应用这些生命周期,所以后面生命周期都会触发到if (isCheckLiftCycle(lifeCycle)) {app.bootstrap = lifeCycle.bootstrap;app.mount = lifeCycle.mount;app.unmount = lifeCycle.unmount;}
- 我们需要先判断子应用是否有生命周期,再将其挂载到子应用app上
- 此时,主应用
beforeLoaded生命周期执行完,开始执行mounted,这个时候,我们就能执行到子应用app上的mount方法,在子应用中做渲染处理// 子应用 export async function mount(app) { console.log('mount'); setMain(app) render(); }
