
原理,通过控制属性的激活和失效达到效果。
第一次,当应用激活时用一个变量
windowSnapshot
copy window上的属性生成快照,此时modifyPropsMap
被修改的属性上面没有记录
当应用失活时对比window上的属性和copy_window上的属性是否有区别,有区别说明有更新,用modifyPropsMap
记录这些属性,然后使用windowSnapshot
恢复window环境
第二次,当应用激活时用一个变量copy window上的属性生成快照,此时modifyPropsMap
不为空,将修改过的属性再添加到window上即可
简易版实现:
function iter(obj, callbackFn) {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) || prop === "clearInterval") {
callbackFn(prop);
}
}
}
//快照沙箱
class SnapshotSandbox {
windowSnapshot = null; //记录快照属性
sandboxRunning = null; //标识是否使用沙箱
modifyPropsMap = {}; //记录被修改过的属性
active() {
this.windowSnapshot = {};
//生成快照
for (const prop in window) {
if (window.hasOwnProperty(prop) || prop === "clearInterval") {
this.windowSnapshot[prop] = window[prop];
}
}
//恢复window环境
Object.keys(this.modifyPropsMap).forEach((p) => {
window[p] = this.modifyPropsMap[p];
});
this.sandboxRunning = true;
}
inactive() {
this.modifyPropsMap = {};
iter(window, (prop) => {
//window上属性和快照上属性不一致
if (window[prop] !== this.windowSnapshot[prop]) {
//记录被修改属性
this.modifyPropsMap[prop] = window[prop];
//将window所有属性恢复为之前copy的window属性
window[prop] = this.windowSnapshot[prop];
}
});
this.sandboxRunning = false;
}
}
let snapshotSandBox = new SnapshotSandbox();
snapshotSandBox.active();
window.app = "vue2";
console.log("get app1:", window.app); //vue2
snapshotSandBox.inactive();
console.log("get app2:", window.app); //undefined
snapshotSandBox.active();
console.log("get app3:", window.app); //vue2
snapshotSandBox.inactive();
网友评论