微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Shadow DOM 样式隔离 &&js沙箱

这种方法可能适用于中台这种嵌套其他子应用的场景,目前没遇到其他使用场景或有更好的解决方

 在线demo

不管是link导入的样色还是<style>标签样色都可以被隔离,不影响shadow dom外层的样式

代码

<!DOCTYPE html>
<html lang="en">

<head>
    <Meta charset="UTF-8">
    <Meta http-equiv="X-UA-Compatible" content="IE=edge">
    <Meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            background: red;
            padding: 10px;
        }
        
        .Box {
            width: 200px;
            height: 200px;
        }
    </style>
</head>

<body>
    <div class="wrap">
        123
        <div class="Box">
            <div class="wrap">
                原来的内容,开启attachShadow后,不在显示
            </div>
        </div>
    </div>
    <script>
        window.addEventListener("DOMContentLoaded", function() {
            var Box = document.querySelector(".Box");
            //开启沙箱模式
            /**
             *   mode 参数:
             *    open控制显示
             *    closed控制不显示
             * attachShadow 函数不能多次调用,
             * **/

            Box.attachShadow({
                mode: 'open'
            });
            var shadow = Box.shadowRoot;
            var gloal = "gloal";

            //样色隔离   DEMO1============================================
            var style = document.createElement("style");
            var innerH = `
              .wrap{
                background:green;
                width:200px;
                height:200px;
              }
            `;
            style.innerHTML = innerH;
            shadow.appendChild(style);
            var wrapShadowBox = document.createElement("div");
            wrapShadowBox.className = "wrap";
            shadow.appendChild(wrapShadowBox);
            //样色隔离   DEMO2============================================
            var style2 = document.createElement("link");
            style2.setAttribute("href", "shadow.css");
            style2.setAttribute("rel", "stylesheet");
            shadow.appendChild(style2);

            //a标签===========
            var aLabel = document.createElement("a");
            aLabel.setAttribute("href", "https://developer.mozilla.org/zh-CN/docs/Web/API/Element/attachShadow");
            aLabel.innerHTML = "aLink"
            shadow.appendChild(aLabel);

            ///js隔离demo=========无效
            var scriptShadowBox = document.createElement("script");
            scriptShadowBox.innerHTML = `
               console.log("scriptShadow document",document.querySelector(".wrap"));
               window.aaaaaaaaaaaaaaaaaa="100";
               bbb=200;
               console.log("隔离 window.aaaaaaaaaaaaaaaaaa", window.aaaaaaaaaaaaaaaaaa,'bbb',bbb)
            `;
            shadow.appendChild(scriptShadowBox);
            console.log("非隔离 window.aaaaaaaaaaaaaaaaaa", window.aaaaaaaaaaaaaaaaaa, 'bbb', bbb);

        })
    </script>
</body>

</html>

浏览器支持:

目前除了IE其他PC平台的浏览器支持良好

废弃:

createShadowRoot 不再支持,请使用上述demo中的attachShadow

Video标签

其实Shadow DOM是非常常见的功能,只是我们没有发觉,例如video标签就用到了Shadow DOM,只是它设置的mode是closed,所以控制板上看不到对应的dom,即使在浏览器上是 可以看到的(例如进度条)

我们打开浏览器的【显示用户代理Shadow Dom】,就可以看到如下的Dom结构

参考:

Web Components | Chaoszhu's Blog

而js沙箱使用proxy或者Object.definedobject 对window的set和get 进行拦截就可以实现

proxy提供拦截的方式更加多,包括deleteProperty.

参考:

JS 沙箱隔离简单实现_大名张无忌的博客-CSDN博客_沙箱隔离

从零开始写一个微前端框架-沙箱篇 - SegmentFault 思否

js沙箱 qiankun

在qiankun中,proxy对象会被在eval+with作为全局对象使用,两个沙箱互相不影响,且可以使用window的功能参考链接

// js 代理沙箱 基本实现
class ProxySandBox {
  constructor() {
    const rawWindow = window
    const proxyWindow = {}
    this.proxy = new Proxy(proxyWindow, {
      get(target, key) { // target为第一个参数(代理对象proxyWindow)
        return target[key] || window[key]
      },
      set(target, key, value) {
        target[key] = value
        return true
      }
    })
  }
}
const ProxySandBox1 = new ProxySandBox()
const ProxySandBox2 = new ProxySandBox()
window.a = 1;
// 沙箱1
((window) => {
  window.a = 2
})(ProxySandBox1.proxy);

// 沙箱2
((window) => {
  window.a = 3
})(ProxySandBox1.proxy)

// 代理沙箱,互不影响window
console.log(window.a) // 1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐