微应用(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>

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

相关推荐
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
问道飞鱼1 小时前
【微服务知识】开源RPC框架Dubbo入门介绍
微服务·rpc·开源·dubbo
龙猫蓝图2 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
peachSoda72 小时前
随手记:简单实现纯前端文件导出(XLSX)
前端·javascript·vue.js
Tttian6222 小时前
Vue全栈开发旅游网项目(11)-用户管理前端接口联调
前端·vue.js·django
CodingBrother2 小时前
软考之面向服务架构SOA
微服务·架构
龙猫蓝图4 小时前
vue el-date-picker 日期选择 回显后成功后无法改变的解决办法
前端·javascript·vue.js
刘志辉5 小时前
Pure Adminrelease(水滴框架配置)
vue.js
工业互联网专业5 小时前
Python毕业设计选题:基于Django+uniapp的公司订餐系统小程序
vue.js·python·小程序·django·uni-app·源码·课程设计
黄景圣5 小时前
CURD低代码程序设计
前端·vue.js·后端