微应用(qiankun)之样式隔离

前言

在上篇文章 微应用(qiankun)之 vite 构建 中,我们在应用的样式隔离方面并没有做过多的介绍。而在实际项目中,这确是一个不容忽视的问题。那么我们应该如何去做这样式隔离呢?接下来本文首先会从 qiankun 提供的样式隔离方案开始进行简单介绍,然后选取合适的方案来实现样式隔离。下面就让我们一起来看看吧!

为什么要做样式隔离

在使用 qiankun 时,我们会发现,当我们在主应用中引入了多个子应用时,子应用的样式会互相影响,这是因为子应用的样式是全局 的,而 qiankun 默认情况下并没有对子应用的样式进行隔离。而我们实际中想要的样式隔离效果又是怎么样的呢?其主要是下面两点:

  1. 子应用样式不会影响到其他子应用或主应用,同时也支持全局样式
  2. 主应用样式可以覆盖各子应用下的指定的样式,不容易影响到其他子应用

基于上面两点,我们需要的样式隔离方案应该是弱隔离型 。那么我们该如何去实现呢?首先,让我们先来了解一下 qiankun 提供的样式隔离方案。

qiankun 提供的样式隔离方案

qiankun 提供了两种样式隔离方案 strictStyleIsolation 和 experimentalStyleIsolation,我们可以根据实际情况来选择合适的方案。下面也会对这两种方案进行介绍,并给出示例代码,方便大家理解。更多详情可参考 qiankun-startopts

strictStyleIsolation

它是严格的样式隔离,也是官方推荐的,主要是通过 shadow dom 来实现的。

shadow dom

shadow dom 是一种浏览器技术,它可以将一个 DOM 节点及其子节点与另一个文档分离。这样它就可以有自己的 DOM 树、CSS 样式、计算样式等等,但它并不是所有浏览器都支持。更多详情可参考 shadow dom。

下面是 qiankun 中 strictStyleIsolation 样式隔离的示例代码:

示例代码

ts 复制代码
import { start, loadMicroApp } from 'qiankun'

// 说明:结合加载子应用方式选择其中一种即可

// 方式1: 启动 qiankun
start({
  sandbox: {
    strictStyleIsolation: true,
  }
})

// 方式2: 手动加载子应用 reactApp
loadMicroApp('reactApp', {
  sandbox: {
    strictStyleIsolation: true,
  }
})

当开启 strictStyleIsolation 后,我们会发现子应用的样式已经被隔离了,同时子应用的样式也无法覆盖主应用的样式了。如下图所示:

结论

通过上面对 shadow dom 的了解,我们会发现它是强隔离型,也并不支持覆盖子应用样式及子应用无法设置全局样式等问题。所以它是不能满足我们需求的。

experimentalStyleIsolation

它是实验性的样式隔离。主要是通过 scoped css 来实现的。

scoped css

scoped css 是一种 css 技术,它可以让 css 样式只作用于当前组件中的元素。这种技术可以用来实现样式隔离。更多详情可参考下面的链接:

下面是 qiankun 中 experimentalStyleIsolation 样式隔离的示例代码:

示例代码

ts 复制代码
import { start, loadMicroApp } from 'qiankun'

// 说明:结合加载子应用方式选择其中一种即可

// 方式1: 启动 qiankun
start({
  sandbox: {
    experimentalStyleIsolation: true,
  }
})

// 方式2: 手动加载子应用 reactApp
loadMicroApp('reactApp', {
  sandbox: {
    experimentalStyleIsolation: true,
  }
})

当开启 experimentalStyleIsolation 后,其实我们可以看到 qiankun 会在外层容器上添加 data-qiankun="子应用名称" 属性,与此同时也会子应用的样式上添加 div[data-qiankun="子应用名称"] 选择器来实现了样式隔离。如下面结构所示:

scss 复制代码
// 子应用名称 = reactApp
div[data-qiankun="reactApp"] .layout {
  // 子应用样式
}

div[data-qiankun="reactApp"] .layout-container {
  // 子应用样式
}

但是在我的项目示例中并没有展现正确的效果,看早前有人提过 issues,可是并没有得到任何回复。不过其他人好像也并没有遇到类似的问题,它或许可能与我项目中的其它地方产生了冲突,如果有知道小伙伴的可以评论区留言哦!示例项目中效果如下图所示:

结论

通过上面对 scoped css 的了解,我们会发现它其实是可以满足我们需求的,但是 qiankun 的 experimentalStyleIsolation 却并没有支持全局样式的设置。故也是 pass,期待 qiankun 后续完善支持!

最终样式隔离方案

综上所述,我们可以得出结论:qiankun 目前提供的两种样式隔离方案并不能满足我们的需求。但给了我们一个思路,那就是 scoped css 方案。故此我们可以自己在项目通过 scoped css 来实现应用的样式隔离来满足我们的需求。下面依次介绍如何在 react 和 vue 中使用 scoped css 来实现样式隔离。

React

在 React 中,我们可以通过 scoped css 来实现样式隔离,它的原理是给每个 class 添加一个 hash 的属性,这样就可以实现样式隔离。vite 构建的 react 项目默认支持 scoped css,我们只需要将样式文件后缀改为 .module.scss 即可

示例代码
tsx 复制代码
import styles from './index.module.scss'

export default () => {
  return (
    <div className={styles.container}>
      <p className='title'>react app</p>
      <button className={styles.button}>button</button>
    </div>
  )
}

index.module.scss 样式文件正常 scss 语法 写即可,不需要做任何处理

scss 复制代码
.container {
  .title {}
  // :global 前缀可以让样式不被隔离,可以在全局使用
  :global.button {}
}

vue

在 vue 中,我们可以通过 scoped 来实现样式隔离,它的原理是给每个 class 添加一个 data-v-xxxx 的属性,这样就可以实现样式隔离。

示例代码

vue 复制代码
<style lang="scss" scoped></style>

文章介绍到这里就结束了,希望对大家有所帮助,如果有什么问题欢迎在评论区留言哦!

相关推荐
高级程序源20 分钟前
django校园寻物通失物招领平台32261-计算机课程设计、毕业设计
vue.js·python·mysql·小程序·django·flask·课程设计
WeiXin_DZbishe32 分钟前
基于springboot宠物领养系统-计算机毕设 附源码【课程设计】94217
vue.js·spring boot·python·django·php·课程设计
WeiXin_DZbishe3 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
WeiXin_DZbishe3 小时前
基于Springboot+AI的kuall音乐广场的设计与实现-计算机毕设 附源码【课程设计】12715
vue.js·人工智能·spring boot·后端·python·php·课程设计
wewowilling3 小时前
认识微服务
java·运维·微服务·springcloud
_馒头3 小时前
pixiJs游戏开发实践 - 跳棋小游戏
javascript·vue.js
AIGC小尼5 小时前
毕设实战|SpringBoot+Vue 实现多个系统项目
vue.js·spring boot·课程设计
众链网络6 小时前
Agent 的成本大头不在“写“,在“判断“:拆解专用决策模型的三层架构
java·开发语言·人工智能·微服务
踩着两条虫8 小时前
我在浏览器里“盖”了一个村:Vue + Three.js 大屏开发踩坑记
前端·vue.js·three.js
我不是阵雨9 小时前
分布式事务难题与实战解法全解析
分布式·微服务·架构