欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

UMI+ 乾坤] 风格污染解决方案

最编程 2024-03-20 16:31:12
...

【UMI+qiankun】样式污染解决方案

本文会给出解决样式污染的最佳解决方案。

一、项目背景

  • 子应用是各个业务线开发的应用,技术栈及UI框架的组合共有如下3种:
    • Vue + antd-vue
    • Vue + ElementUI
    • Umi + antd
  • 父应用是后面才立项的应用,使用 ant-design-pro ( V5版本 )生成,为自带 antd 的工程化 Umi 项目( react 系)。

二、样式污染

  • 1、父子应用都有用 antd,但是父子应用使用的版本不同,相同类名不同版本的实现不同。举一个简单例子:
# 新版本
.ant-tabs{
  display: flex;
}
# 旧版本
.ant-tabs{
  display: block;
}

# 新版本
.xxx{
  # 新增了某个样式a
}
# 旧版本
.xxx{
   # 新增了某个样式b
}

这就导致父子应用可能相互影响。

  • 2、父子应用都用了某个类名,但是具体样式不同,导致父应用影响子应用(情况与1类似,但是解决方案不同)。
# 父应用
.row {
  # 父应用的实现
}
# 子应用
.row{
  # 子应用的实现
}
  • 3、父应用或者子应用使用了 reset.css 或者某些类似的样式库,影响子应用或父应用。举例,父应用有 *{box-sizing: border-box;},但是子应用不需要,而且会影响他们。

三、解决方案

1、针对父子应用使用不同版本的 antd 导致的样式冲突,可以在父应用的 antd 里面增加特别的前缀,正好 antd 支持配置前缀 prefixCls

  • UMI 项目
# .umirc.ts or config/config.ts 文件
export default defineConfig({
  antd: {
    config: {
      prefixCls: 'bapAnt', # 修改HTML里面的类名前缀
    },
  },
  lessLoader: { modifyVars: { '@ant-prefix': 'bapAnt' } }, # 对应修改生成的 antd 样式类名
}
  • UMI 项目,以VUE为例
<ConfigProvider prefixCls="bapAnt">
    <App/>
</ConfigProvider>
# vue.config.js
{
  # ...其他配置,
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          modifyVars: {prefixCls:'bapAnt"},
          javascriptEnabled: true
        }
      }
    }
  },
  # ...其他配置,
}

这样配置过后,父子应用的不同 antd 版本就不会有样式冲突的问题。

注意:如果样式文件有改写/覆盖原本的 antd样式,即以.ant 开头的样式,记得全局替换为 .bapAnt (为了防止自己也写有 .ant 开头的,建议使用 .bapAnt- 替换 .ant-,增加容错。)

2、针对父子应用都使用了相同某个样式类名,子应用无法控制,但是父应用是我们自己写的,可以直接使用 CSS MODULE 的写法编写样式。

# less 文件
.testCls {
  # :global 可以覆盖全局的样式,透传下去
  :global {
    # 注意这里的 .ant- 开头的样式,已经替换成了 .bapAnt-
    .bapAnt-tabs-content-holder {
      display: none;
    }
}
# tsx 文件
import styles from './index.less';
# 使用如: <div className={styles.testCls}></div>

使用 CSS MODULE 后,父子一个亿使用相同样式类名的样式冲突问题也可以完美解决。

3、(3a)针对父应用的全局 reset.css 或者某些类似的样式库影响了子应用;(3b)或者反过来,子应用有,父应用没有,子应用会影响父应用。

这里面最重要最有影响的样式就是 通配符 *,我们直接在子应用的 body 里面增加一个特定样式,然后把通配符样式包裹进去,然后把里面的样式实现改为自己想要的即可。这样因为权重优先级,父应用的就不会覆盖子应用的。

如果是(3b)的情况,也是在子应用相应地处理(因为父应用里面处理没用)。

PS:当然最好是最开始就设计好,统一技术栈,统一UI库,统一样式库(重置样式等),我们是后来才搞的父应用,所以情况不同。

4、题外话

对于 qiankun 自带的配置项

{ sandbox: 
    { strictStyleIsolation: true, // 严格沙箱 
    experimentalStyleIsolation: true // 实验性沙箱
    }
}

目前不建议开启,否则会造成自应用的全局样式丢失!!所以还是按照我的3板斧来,嘻嘻~~