一.思考
微前端应用加载 刚开始我加载A应用 window.a B应用 window.a 怎样可以俩个应用里的a属性互不影响
二.什么是沙箱
①应用的运行 从开始到结束 切换后不会影响全局
②创造一个干净的环境给这个子应用使用,当切换时,可以选择丢弃属性和恢复属性
三.实现
单应用切换 JS沙箱 乾坤的俩种机制
①快照沙箱
举例 : 比如想看你变没变样 一年前拍一张 再拍一张 (将区别保存起来) 在回到一年前 相当于这一年干了很多事 等会要是想还原 就可以把区别在应用到这一年
核心:前后比对,把区别保存起来,在回到以前,如果想在恢复这个沙箱就把刚才的区别运行回来
缺点: 如果是多个子应用就不能使用这种方式了,可以完全使用es6 proxy
class SanpshotSandbox {
constructor() {
this.proxy = window; //window属性
this.modifyPropsMap = {} //记录在window上的修改
this.active();
}
// 激活沙箱
active() {
this.windowSnapshot = {}; //拍照
for (const prop in window) {
if (window.hasOwnProperty(prop)) {
this.windowSnapshot[prop] = window[prop];
}
}
// 将上次的修改进行一个应用 到 当前的window上
Object.keys(this.modifyPropsMap).forEach(p => {
// 将上次修改过得赋到window上
window[p] = this.modifyPropsMap[p];
})
}
// 丢弃沙箱
inactve() {
for (const prop in window) {
if (window.hasOwnProperty(prop)) {
if (window[prop] !== this.windowSnapshot[prop]) {
// 拿现在的和一年前的作比较 如果他俩不一样了 说明换这个属性有变化 有变化就把变化记录在变化表里
this.modifyPropsMap[prop] = window[prop]
// 最后在将window变回一年前
window[prop] = this.windowSnapshot[prop]
}
}
}
}
}
let sandbox = new SanpshotSandbox();
//通过沙箱返回一个代理
((window) => {
window.a = 1;
window.b = 2;
console.log(window.a, window.b); // 1 2
sandbox.inactve(); //失去激活后
console.log(window.a, window.b); // undefined undefined
sandbox.actve(); //激活
console.log(window.a, window.b); // 1 2
})(sandbox.proxy); //sandbox.proxy就是window
②proxy沙箱
原理 :new俩个盒子 这俩个盒子传入的属性并不是window 取值的时候先会取代理的window 取不到才会取原window 这种方案不会影响全局window
优点:可以实现多应用沙箱 把不同的应用用不同的代理来处理
缺点:但是有些浏览器不支持proxy使用
class ProxySandbox {
constructor(){
const rawWindow = window;
const fakeWindow = {};
const proxy = new Proxy(fakeWindow,{
set(target,p,value){
target[p] = value;
return true
},
get(target,p){
return target[p] || fakeWindow[p];
}
});
this.proxy = proxy;
}
}
let sandbox1 = new ProxySandbox();
let sandbox2 = new ProxySandbox();
window.a = 1;
((window) => {
window.a = 'hello';
console.log(window.a);
})(sandbox1.proxy);
((window) => {
window.a = 'hello';
console.log(window.a);
})(sandbox2.proxy);
四.对比
俩种情况 ①父应用和子应用 ②多应用
image.png
网友评论