微前端中如何有效解决js、样式和元素隔离的问题?

2026-04-01 14:352阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1307个文字,预计阅读时间需要6分钟。

微前端中如何有效解决js、样式和元素隔离的问题?

目录 + WebComponent 介绍 + js 隔离 + 问题 + 解决 + 方法一:用 Proxy 代理 + 方法二:用快照 + 样式隔离 + 问题 + 解决 + 方法一:样式增加不同前缀 + 方法二:Shadow Dom + 元素隔离 + WebComponent 介绍 + 微前端框架中,js 隔离、样式隔离

目录
  • WebComponent 介绍
  • js隔离
    • 问题
    • 解决
      • 方法一用 Proxy 代理
      • 方法二 用快照
  • 样式隔离
    • 问题
      • 方法一 样式增加不同前缀
      • 方法二 ShadawDom
  • 元素隔离

    WebComponent 介绍

    微前端框架中,js隔离、样式隔离、元素隔离是必须解决的三个问题,下面我们就来分别说说这三个问题是什么?怎么解决?

    微前端中如何有效解决js、样式和元素隔离的问题?

    涉及的核心点是 Proxy,WebComponent,shadowDOM

    WebComponent 不在这三个问题中,但是我们做个简单介绍

    浏览器默认的标签有 div,a,p等等,浏览器是会自动识别,并且有默认的事件和样式。

    浏览器相对于提供了WebComponent,我们可以自定义Html标签,注意规定自定义标签需要包含横线,如<user-card>,父类都是HTMLElement

    attachShadow 是大多数标签都支持的,比如 div,p,selection,但是a,ul,li等不支持,如果执行attachShadow,那么组件的html结构会挂在shadowRoot下,否则直接挂着组件下。

    用法

    class UserCard extends HTMLElement { static get observedAttributes() {return ['name', 'url']; } constructor() { super(); // 可以创Shadom,通过this.shadowRoot获取 // this.attachShadow({ mode: 'open' }) } connectedCallback (){ console.log('钩子,元素append到ducument触发') } disconnectedCallback (){ console.log('钩子,元素从document删除触发') } // 只有observedAttributes 中监听的属性name,url变化会触发下面回调 attributeChangedCallback (attr, oldVal, newVal){ console.log('钩子,元素属性改变时触发') } } window.customElements.define('user-card', UserCard);

    更新细节查看 web自定义元素

    js隔离

    问题

    主要是很对全局变量window

    • 情况1:都对全局变量赋值

    应用A,写 window.r = 1;

    然后有应用B,又写 window.r = 2,这就乱套了

    • 情况2:都设置事件

    应用A,window.addEventListener('click',()=>console.log('A'));

    应用B,window.addEventListener('click',()=>console.log('B'));

    这就乱套了

    解决

    对应全局对象,各个应该要独立,怎么实现呢,有两种方法

    方法一用 Proxy 代理

    es2015 Reflect属于一个静态类或者设置属性等用法

    const rawWindow = window const proxyWindow = new Proxy({},{ get: (target, key): unknown => { // 原 target 上有就返回,否则返回 rawWindow 属性 return Reflect.has(target, key) ? Reflect.get(target, key) : Reflect.get(rawWindow, key) }, set: (target, key, value): boolean => { if(!Object.prototype.hasOwnProperty.call(target, key) && Object.prototype.hasOwnProperty.call(rawWindow, key)){ const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key) const { configurable, enumerable, writable, set } = descriptor! // set value because it can be set rawDefineProperty(target, key, { value, configurable, enumerable, writable: writable ?? !!set, }) } else { Reflect.set(target, key, value) } } })

    将 window.r = 1 和 window.addEventListener('click',()=>console.log('A')) 包括到自执行函数里面

    A和B互不干扰

    ;(function(window){ window.r = 1 window.addEventListener('click',()=>console.log('A')) })(proxyWindowA)

    ;(function(window){ window.r = 2 window.addEventListener('click',()=>console.log('B')) })(proxyWindowB)

    方法二 用快照

    快照隔离有个前提条件是,当前还有一个应用显示,不能出现多个应用并存显示在界面上,应用A,B切换时,比如当前应用是A,现在要切入到应用B

    • 暂存起来应用A的全局变量和事件
    • 恢复全局变量和事件到应用A之前
    • 检查之前是否保持有应用B的全局变量和事件,如果有,则载入

    样式隔离

    同理,各个应用之前可能相互设置标签样式,会相互影响,或者影响全局样式,比如应用A给body设置样式,应用B也给body设置样式

    方法一 样式增加不同前缀

    每个应用通过前缀独立区分开,京东micro-app默认是采用的这个策略,唯一注意的一个小点是,基座样式会影响子应用的样式,所以需要注意基座中不要写太多样式

    方法二 ShadawDom

    大多数Html标签都有 attachShadow() 方法给指定的元素挂载一个 Shadow DOM。参数是open或closed

    ShadawDom 样式绝对隔离,不用加前缀,如下图

    用法

    //open 是外界可以访问到Element.shadowRoot再访问到内部元素,closed就是完全不能访问内部元素 var shadowroot = element.attachShadow('open|closed')

    元素隔离

    元素隔离是 基座应用和子应用都有一个元素<div id='root'></div>,此时子应用通过document.querySelector('#root'),因为js隔离已经做了代理,此时document.querySelector只是子应用本身了

    以上就是微前端之 js隔离 样式隔离 元素隔离问题详解的详细内容,更多关于微前端js 样式 元素隔离的资料请关注易盾网络其它相关文章!

    本文共计1307个文字,预计阅读时间需要6分钟。

    微前端中如何有效解决js、样式和元素隔离的问题?

    目录 + WebComponent 介绍 + js 隔离 + 问题 + 解决 + 方法一:用 Proxy 代理 + 方法二:用快照 + 样式隔离 + 问题 + 解决 + 方法一:样式增加不同前缀 + 方法二:Shadow Dom + 元素隔离 + WebComponent 介绍 + 微前端框架中,js 隔离、样式隔离

    目录
    • WebComponent 介绍
    • js隔离
      • 问题
      • 解决
        • 方法一用 Proxy 代理
        • 方法二 用快照
    • 样式隔离
      • 问题
        • 方法一 样式增加不同前缀
        • 方法二 ShadawDom
    • 元素隔离

      WebComponent 介绍

      微前端框架中,js隔离、样式隔离、元素隔离是必须解决的三个问题,下面我们就来分别说说这三个问题是什么?怎么解决?

      微前端中如何有效解决js、样式和元素隔离的问题?

      涉及的核心点是 Proxy,WebComponent,shadowDOM

      WebComponent 不在这三个问题中,但是我们做个简单介绍

      浏览器默认的标签有 div,a,p等等,浏览器是会自动识别,并且有默认的事件和样式。

      浏览器相对于提供了WebComponent,我们可以自定义Html标签,注意规定自定义标签需要包含横线,如<user-card>,父类都是HTMLElement

      attachShadow 是大多数标签都支持的,比如 div,p,selection,但是a,ul,li等不支持,如果执行attachShadow,那么组件的html结构会挂在shadowRoot下,否则直接挂着组件下。

      用法

      class UserCard extends HTMLElement { static get observedAttributes() {return ['name', 'url']; } constructor() { super(); // 可以创Shadom,通过this.shadowRoot获取 // this.attachShadow({ mode: 'open' }) } connectedCallback (){ console.log('钩子,元素append到ducument触发') } disconnectedCallback (){ console.log('钩子,元素从document删除触发') } // 只有observedAttributes 中监听的属性name,url变化会触发下面回调 attributeChangedCallback (attr, oldVal, newVal){ console.log('钩子,元素属性改变时触发') } } window.customElements.define('user-card', UserCard);

      更新细节查看 web自定义元素

      js隔离

      问题

      主要是很对全局变量window

      • 情况1:都对全局变量赋值

      应用A,写 window.r = 1;

      然后有应用B,又写 window.r = 2,这就乱套了

      • 情况2:都设置事件

      应用A,window.addEventListener('click',()=>console.log('A'));

      应用B,window.addEventListener('click',()=>console.log('B'));

      这就乱套了

      解决

      对应全局对象,各个应该要独立,怎么实现呢,有两种方法

      方法一用 Proxy 代理

      es2015 Reflect属于一个静态类或者设置属性等用法

      const rawWindow = window const proxyWindow = new Proxy({},{ get: (target, key): unknown => { // 原 target 上有就返回,否则返回 rawWindow 属性 return Reflect.has(target, key) ? Reflect.get(target, key) : Reflect.get(rawWindow, key) }, set: (target, key, value): boolean => { if(!Object.prototype.hasOwnProperty.call(target, key) && Object.prototype.hasOwnProperty.call(rawWindow, key)){ const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key) const { configurable, enumerable, writable, set } = descriptor! // set value because it can be set rawDefineProperty(target, key, { value, configurable, enumerable, writable: writable ?? !!set, }) } else { Reflect.set(target, key, value) } } })

      将 window.r = 1 和 window.addEventListener('click',()=>console.log('A')) 包括到自执行函数里面

      A和B互不干扰

      ;(function(window){ window.r = 1 window.addEventListener('click',()=>console.log('A')) })(proxyWindowA)

      ;(function(window){ window.r = 2 window.addEventListener('click',()=>console.log('B')) })(proxyWindowB)

      方法二 用快照

      快照隔离有个前提条件是,当前还有一个应用显示,不能出现多个应用并存显示在界面上,应用A,B切换时,比如当前应用是A,现在要切入到应用B

      • 暂存起来应用A的全局变量和事件
      • 恢复全局变量和事件到应用A之前
      • 检查之前是否保持有应用B的全局变量和事件,如果有,则载入

      样式隔离

      同理,各个应用之前可能相互设置标签样式,会相互影响,或者影响全局样式,比如应用A给body设置样式,应用B也给body设置样式

      方法一 样式增加不同前缀

      每个应用通过前缀独立区分开,京东micro-app默认是采用的这个策略,唯一注意的一个小点是,基座样式会影响子应用的样式,所以需要注意基座中不要写太多样式

      方法二 ShadawDom

      大多数Html标签都有 attachShadow() 方法给指定的元素挂载一个 Shadow DOM。参数是open或closed

      ShadawDom 样式绝对隔离,不用加前缀,如下图

      用法

      //open 是外界可以访问到Element.shadowRoot再访问到内部元素,closed就是完全不能访问内部元素 var shadowroot = element.attachShadow('open|closed')

      元素隔离

      元素隔离是 基座应用和子应用都有一个元素<div id='root'></div>,此时子应用通过document.querySelector('#root'),因为js隔离已经做了代理,此时document.querySelector只是子应用本身了

      以上就是微前端之 js隔离 样式隔离 元素隔离问题详解的详细内容,更多关于微前端js 样式 元素隔离的资料请关注易盾网络其它相关文章!