微应用(qiankun)之样式隔离

前言

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

为什么要做样式隔离

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

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

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

qiankun 提供的样式隔离方案

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

strictStyleIsolation

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

shadow dom

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

下面是 qiankunstrictStyleIsolation 样式隔离的示例代码:

示例代码

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 样式只作用于当前组件中的元素。这种技术可以用来实现样式隔离。更多详情可参考下面的链接:

下面是 qiankunexperimentalStyleIsolation 样式隔离的示例代码:

示例代码

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 的了解,我们会发现它其实是可以满足我们需求的,但是 qiankunexperimentalStyleIsolation 却并没有支持全局样式的设置。故也是 pass,期待 qiankun 后续完善支持!

最终样式隔离方案

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

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

相关推荐
大叔_爱编程16 分钟前
wx203基于ssm+vue+uniapp的教学辅助小程序
vue.js·小程序·uni-app·毕业设计·ssm·源码·课程设计
关山月21 分钟前
6 个常见的 React 反模式,正在损害你的代码质量
react.js
MaCa .BaKa25 分钟前
25-智慧旅游系统(协同算法)三端
java·javascript·vue.js·spring boot·tomcat·maven·旅游
kiss strong1 小时前
Spring Boot向Vue发送消息通过WebSocket实现通信
vue.js·spring boot·websocket
猫猫不是喵喵.9 小时前
vue 路由
前端·javascript·vue.js
bin915310 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例12,TableView16_12 拖拽动画示例
前端·javascript·vue.js·ecmascript·deepseek
拉不动的猪11 小时前
vue自定义“权限控制”指令
前端·javascript·vue.js
拉不动的猪11 小时前
刷刷题48 (setState常规问答)
前端·react.js·面试
Ada_疯丫头12 小时前
「React」React Router v7 framework qiankun window is not defined
react.js
魔云连洲12 小时前
Vue2和Vue3响应式的基本实现
开发语言·前端·javascript·vue.js