当前位置: 首页 > news >正文

微前端场景下如何做样式隔离?

问题示例

className 命名重复导致的样式冲突

在主应用和子应用上分别使用 div 元素插入一段标题,两个 div 元素使用相同的 class 名 title,分别在 class 中设置文字颜色,主应用 color 值为 yellow,子应用为 red。

由于子应用的样式晚于主应用加载,所以主应用的样式会被覆盖

以上问题在同时加载多个子应用时也会存在:各个应用之间也可能存在同名的 className 或者给相同条件的选择器添加了样式, 那么最终只有优先级最高的样式才会生效。要确保应用之间的样式不会互相影响,就需要对应用间的样式进行隔离。

html、body 标签的样式冲突

html 、 body 标签, 在各个应用中都是唯一的元素,其样式必然会对主应用的样式产生影响。

解决方案

为了以上样式冲突问题,通常有以下两种思路:

  • 通过样式命名 和 样式优先级解决
  • 通过宿主环境隔离来达到样式隔离

样式命名 和 样式优先级

假设各个应用之间的样式 className 都是全局唯一的, 那么不同 className 下的样式就一定不会发生冲突。

再加上样式优先级来配合解决,就能解决标签选择器的样式冲突:

  • 例如在原 className 、标签选择器前面再添加一个 selector
  • 标签选择器 + 属性选择器

子应用改造

这里需要处理的样式也分为以下两种:

UI 组件库等引入的全局样式

默认情况下,UI 组件库的 prefixCls 都是相同的,不过它们提供了 ConfigProvider 可以用来修改 UI 组件库全局样式的 prefixCls。

自定义样式

通过 BEM、CSS Modules、 CSS in JS 等手段来获得与其他应用不同的选择器名,来规避样式冲突。

或者直接使用 postcss 的插件,在编译阶段给所有样式添加 prefix selector。

add prefix selector

主应用在运行时统一转换样式

京东的微前端框架MicroApp的样式隔离是默认开启的,开启后会以<micro-app>标签作为样式作用域,利用标签的name属性为每个样式添加前缀,将子应用的样式影响禁锢在当前标签区域。

.test {color: red;
}/* 转换为 */
micro-app[name=xxx] .test {color: red;
}

但主应用的样式依然会对子应用产生影响,如果发生样式污染,推荐通过约定前缀或CSS Modules方式解决。

宿主环境隔离

Shadow DOM

附加并隐藏在常规 DOM 下的节点叫做 Shadow DOM —— 它以 Shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,就和普通的 DOM 元素一样,它可以通过方法添加子节点、设置属性,以及为节点添加自己的样式,隐藏的 DOM 样式和其余 DOM 是完全隔离的,类似于 iframe 的样式隔离效果。

如何创建

可以使用 shadowHostElement.attachShadow() 方法来将一个 shadow root 附加到调用方法的元素上。它接受一个配置对象作为参数,该对象有一个 mode 属性,值可以是 open 或者 closed

let shadowRoot = shadowHostElement.attachShadow({mode: 'open'});
let shadowRoot = shadowHostElement.attachShadow({mode: 'closed'});

open 表示可以通过页面内的 JavaScript 来获取 Shadow DOM,例如使用 Element.shadowRoot 属性:

let shadowRoot = shadowHostElement.shadowRoot;

如果将 mode 设置为 closed,那么elementRef.shadowRoot 将会返回 null

浏览器中的某些内置元素就是如此,例如<video>,就包含了不可访问的 Shadow DOM。

为 shadow DOM 添加样式

我们可以通过创建<style> 元素为 Shadow DOM 添加样式,也可以通过创建<link> 元素引用外部样式表。

// 使用 style 元素为 shadow DOM 添加样式
const style = document.createElement('style');
style.textContent = `.title {color: blue;}
`;
shadow.appendChild(style);// 使用 link 标签为 Shadow DOM 添加样式
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');
shadow.appendChild(linkElem);

优点

  1. 完全隔离 CSS 样式

缺点

  1. 在使用一些 antd Select 组件的时候(很多情况下都是将 open 后的元素默认添加到了 document.body 上 )这个时候它就跳过了阴影边界,逃逸到主应用里面,导致样式丢失,这时候就需要去子应用中手动修正该弹出元素的挂载节点(例如使用 antd select 的 getPopupContainer)。

  2. 会与 react v17 之前的事件代理机制产生冲突,React v16 会各种事件处理函数代理到 document ,但是根据 Shadow DOM 的事件模型,从 Shadow DOM 中冒泡出来的事件 target 都会被调整成 shadow host, 导致 react v16 无法通过 event.target 找到对应的元素并触发事件。

  3. 兼容性还行,需要考虑。

总结

样式隔离实现起来不复杂,各种方案都有其局限性。目前比较稳定的方案还是使用 css Modules 之类的工具配合团队之间协商好样式前缀,从样式命名和优先级上解决问题。

主应用的样式依然可以影响到子应用,优先级也可能会被 !important 等操作被破坏,不过大多数场景下足够了

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • IP地址封装类(InetAddress类)
  • 清华大学在感前光学计算方向获得进展
  • 疯狂Java讲义_08_泛型
  • 2024年云计算企业CRM应用与选型研究报告
  • 如何看待云原生数据库一体化的技术趋势?
  • 文件属性获取
  • Java 并发集合:阻塞队列集合介绍
  • .NET8使用VS2022打包Docker镜像
  • Xshell8最新版体验(业界最强大的SSH连接工具)
  • ZPScan网络扫漏工具-子命令说明
  • C#如何解决引用类型的“深度”克隆问题
  • 细说MCU检测按键输入的外部中断和修改HAL_GPIO_EXTI_IRQHandler() 的实现方法
  • 贪吃蛇(使用QT)
  • 连接投影仪/显示器只能扩展不能复制的解决方案
  • 七夕警示:探索社工库与网络搜索下的个人隐私泄露与保护策略
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • input实现文字超出省略号功能
  • Javascript弹出层-初探
  • js数组之filter
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Node项目之评分系统(二)- 数据库设计
  • Redis学习笔记 - pipline(流水线、管道)
  • 编写符合Python风格的对象
  • 多线程 start 和 run 方法到底有什么区别?
  • ------- 计算机网络基础
  • 利用DataURL技术在网页上显示图片
  • 两列自适应布局方案整理
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 学习使用ExpressJS 4.0中的新Router
  • 转载:[译] 内容加速黑科技趣谈
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #微信小程序(布局、渲染层基础知识)
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (Forward) Music Player: From UI Proposal to Code
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (十六)视图变换 正交投影 透视投影
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)Windows2003安全设置/维护
  • (转载)Linux网络编程入门
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net core 管理用户机密
  • .Net 代码性能 - (1)
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net 获取url的方法
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)