1.创建一个主项目,相当于是基座,在主项目里面通过hashchange或者popstate监听路由的变化,切换路由时,进行子项目activeRule的匹配,然后获取到对应的子项目的entry入口
```js
const app = apps.find(item => {
return window.location.pathname.startsWith(item.activeRule)
})
// 3.加载子应用
const html = await fetch(app.entry).then(res => res.text())
```
2.通过entry入口,获取子应用的html,通过innerHTML放到基座的container容器中,这里的获取方式是通过fetch请求方法
```js
const html = await fetch(app.entry).then(res => res.text())
const container = document.querySelector(app.container)
container.innerHTML = html
```
3.获取script标签,核心代码
1.获取template中所有的script标签,如果script标签存在src属性,说明请求的是一个js,那么把这个地址存到promise.all里面,如果没有src属性,说明是一段立即执行的script代码,那么拿到script标签innerHTML里的内容
2. 由于将src的请求执行时是通过fetch方式,所以如果是jsonp跨域请求,会获取不到
```js
// 获取所有的 script 节点
const scripts = template.querySelectorAll('script')
// 获取所有的 script 标签
function getExternalScripts() {
console.log(Array.from(scripts), 1111)
const scriptsArr = Array.from(scripts).map(script => {
const src = script.getAttribute('src')
if (!src) {
return Promise.resolve(script.innerHTML)
} else {
let srcUrl = src.startsWith('http') ? src : `${url}/${src}`
return fetchResource(srcUrl)
}
})
return Promise.all(scriptsArr)
}
```
4.提供全局变量,子应用可以根据这个来选择是独立渲染,还是挂载到基座上
```js
// 配置全局环境变量
window.__POWERED_BY_QIANKUN__ = true
```
5.子应用里打包导出的格式要设置成umd格式,目的是为了兼容不同的模块规范,打包的结果是一个立即执行函数,会执行子应用的代码,将结果返回到window上(umd规范会判断兼容哪一种)
```js
// node commonJs模块规范
if (typeof exports === 'object' && typeof module === 'object') {
module.exports = factory()
}
// amd 模块规范
else if (typeof define === 'funciton' && define.amd) define([], factory)
// commonjs es6的 import 规范
else if (typeof exports === 'object')
// 如果都不是就是在window上
else
```
6.手动构造了一个commonJS环境
```js
// 手动构造一个commonJs模块环境
const module = { exports: {} }
const exports = module.exports
scripts.forEach(code => {
// eval上的代码可以访问外部变量
eval(code)
})
console.log(module.exports) // 拿到了子应用内部的导出
```
- JavaScript
- 1. DOM事件流
- 2. 模拟 new, Object create(), bind
- 5. 封装函数进行字符串驼峰命名的转换
- 6. 什么是promise
- 7. 判断一个数是否为数组
- 10. __proto__和prototype以及原型,原型链,构造函数
- 11. 继承
- 12. 闭包
- 13. 回调函数
- 14. var 和 let 区别
- 15. this、bind、call、apply
- 16.undefined和null的区别
- 17.内存泄漏
- 18.垃圾回收机制
- html css
- 1. 元素垂直水平居中
- 2. 清除浮动
- 3. bootstrap栅格系统
- 4. px rpx em rem vw 的区别
- 5. 两种盒子模型
- 6. 合集
- web类
- 1. html5的新特性以及理解(web标签语义化)
- 2. 什么是路由,关于前端路由和后端路由
- 3. 对优质代码的理解
- 4. cookie 和 sessionStorage和localStorage
- 5. 浏览器内核
- 6. http 状态码
- 7. href 和 src 的区别
- 8. link 和 @import 的区别
- 9. http 状态码
- 10. websocket
- 11. 浏览器解析url
- 12.http缓存
- vue
- 1.vue2和vue3有哪些区别
- 1. 对 mvvvm 的理解
- 2. mvvm的优缺点
- 3. 数据双向绑定的原理
- 4. 生命周期
- 5. 组件如何通信
- 6. computed和watch的区别
- 7. proxy 和 Object.defineProperty
- 8. 虚拟dom和 diff算法
- 9. 路由的嵌套与传参
- 10. 路由导航钩子
- 11. axios 的理解
- 12. vue自定义指令 diretive
- 13. diff 的实现
- 14. 实现一个简单的双向绑定
- 15. 为什么 data 是一个函数
- 题谱
- js
- 手写篇
- css
- vue
- react
- 算法
- 自我介绍
- 八股文
- 源项目地址
- 1.计算机网络
- 2.浏览器
- 3.html和css
- 4.javascript
- 6.typescript
- 7.vue
- 8.react
- 大厂面试
- 面试题大全
- 常见性能优化
- 面试实战
- 面试分析
- 押题
- 1.微前端在项目中的实际应用
- 2.性能优化
- vue相关
- 1.说一说HashRouter和HistoryRouter的区别和原理
- 无敌之路,牛客网面试题自测记录
- 前端基础
- 1.html
- 2.js基础
- 珠峰性能优化
- WebWorker
- url到渲染
- 浏览器加载机制
- 自我介绍1
- 手写题
- 1.compose
- 2.setTimeout模拟setInterval
- 3.手写数组拍平
- 4.手写promise.all
- 5.手写深拷贝
- webpack
- 实战