一、加载和解析js
因为一般现在前端的页面大多都不是静态页面,而是动态页面,一个页面的渲染完成,不止是只有 html 部分,还有逻辑处理的 js 和 使页面变得精美的 css。
在
main/micro/loader/index.js
中添加getResources
javascript/** * 获取 js * @param root * @param entry * @return {Promise<(string|*[])[]>} */ export const getResources = async (root, entry) => { const scriptUrl = [] const script = [] const dom = root.outerHTML function deepParse (element) { const children = element.children const parent = element.parent // 第一步处理位于 script 中的内容 if (element.nodeName.toLowerCase() === 'script') { const src = element.getAttribute('src') if (!src) { script.push(element.outerHTML) } else { if (src.startsWith('http')) { scriptUrl.push(src) } else { scriptUrl.push(`http:${entry}/${src}`) } } if (parent) { parent.replaceChild(document.createElement('此 js 文件已经被微前端替换'), element) } } // link 也会有js 内容 if (element.nodeName.toLowerCase() === 'link') { const href = element.getAttribute('href') if (href.endsWith('.js')) { if (href.startsWith('http')) { scriptUrl.push(href) } else { scriptUrl.push(`http:${entry}/${href}`) } } } for (let i = 0; i < children.length; i++) { deepParse(children[i]) } } deepParse(root) return [dom, scriptUrl, script] }
在
main/micro/loader/index.js
中parseHtml
调用javascriptexport const parseHtml = async (entry) => { // axios ajax fetch const html = await fetchResource(entry) const div = document.createElement('div') div.innerHTML = html let allScript = [] // 标签、link、script const [dom, scriptUrl, script] = await getResources(div, entry) const fetchedScript = await Promise.all(scriptUrl.map(async item => fetchResource(item))) allScript = script.concat(fetchedScript) return [dom, allScript] }
js 执行
创建
main/micro/sandbox/performScript.js
javascript/** * 执行js脚本 方式一 * @param script */ export const performScriptForFunction = (script) => { new Function(script).call(window, window) } /** * 执行js脚本 方式二 * @param script */ export const performScriptForEval = (script) => { eval(script) }
在
main/micro/loader/index.js
中的loadHtml
方法执行调用javascriptimport { performScriptForFunction } from '../sandbox/performScript' /** * 加载html方法 */ export const loadHtml = async (app) => { // 1. 子应用需要显示在哪里 const container = app.container // 2. 子应用的入口 const entry = app.entry const [dom, scripts] = await parseHtml(entry) const ct = document.querySelector(container) if (!ct) { throw new Error('容器不存在,请查看') } ct.innerHTML = dom scripts.forEach(item => { performScriptForFunction(item) }) return app }