qiankun 框架是怎么做的样式隔离

Qiankun 是一个微前端框架,它在技术上采用了 Web Components 技术实现样式隔离。具体来说,Qiankun 利用 Shadow DOM 的特性,在应用程序容器中创建一个隔离的 DOM 树,使得每个子应用都可以拥有自己独立的样式作用域。

在 Qiankun 中,每个子应用都被封装为一个 Custom Element,这个 Custom Element 包含了子应用所需的所有 HTML、CSS 和 JavaScript 代码,并使用 Shadow DOM 将其包裹起来。由于 Shadow DOM 具有隔离性,因此子应用中声明的 CSS 样式只会作用于其内部,不会影响到其他子应用或主应用。

此外,Qiankun 还提供了一些全局 CSS 变量和类名规范,使得子应用之间的样式命名冲突问题得以解决,同时也能够很好地保持各子应用的样式风格一致性。

shadow Dom

Shadow DOM 是一种将 HTML、CSS 和 JavaScript 封装在一个组件中的技术,它使开发者能够创建具有独立作用域的 Web 组件。

使用 Shadow DOM,您可以将 HTML、CSS 和 JavaScript 封装在一个自定义元素内部,从而防止其中的样式和行为影响到文档中的其他元素。这意味着您可以创建可重复使用的组件,而无需担心与其他组件之间的冲突。

若要使用 Shadow DOM,您需要通过以下步骤创建和应用它:

创建一个自定义元素:您可以通过 document.createElement() 方法创建一个自定义元素,并使用 customElements.define() 方法将其注册到文档中。

创建 Shadow DOM:在自定义元素中,使用 element.attachShadow() 方法创建一个 Shadow DOM。该方法返回一个 ShadowRoot 对象,您可以向其中添加 HTML、CSS 和 JavaScript 代码。

编写样式和逻辑:在 Shadow DOM 中编写您想要的样式和逻辑。

插入 Shadow DOM:最后,在自定义元素中使用 element.appendChild() 方法将 Shadow DOM 插入到自定义元素中。

完成以上步骤后,您的自定义元素就可以作为一个独立的 Web 组件使用了。其他开发者可以在其项目中使用该组件,而无需担心与其他组件之间的干扰。

<my-element></my-element>
// 定义一个自定义元素
class MyElement extends HTMLElement {
  constructor() {
    super();

    // 创建一个 Shadow DOM
    const shadow = this.attachShadow({ mode: 'open' });

    // 创建一个段落元素,并设置样式和内容
    const p = document.createElement('p');
    p.textContent = 'Hello, World!';
    p.style.color = 'red';

    // 插入段落元素到 Shadow DOM 中
    shadow.appendChild(p);
  }
}

// 注册自定义元素
customElements.define('my-element', MyElement);

乾坤demo代码

主应用代码:

import { registerMicroApps, start } from 'qiankun';
import styleLoader from './styleLoader';

// 定义子应用列表
const microApps = [
  {
    name: 'sub-app',
    entry: '//localhost:7100',
    container: '#sub-app-container',
    activeRule: '/sub-app',
  },
];

// 注册子应用
registerMicroApps(microApps, {
  // 加载子应用之前,预加载子应用的样式
  beforeLoad: (app) => {
    return styleLoader.load(app);
  },
});

// 启动 Qiankun
start();

styleLoader.js文件代码:

const cache = {};

export default {
  async load(app) {
    if (cache[app.name]) {
      return cache[app.name];
    }

    const cssList = await Promise.all(
      app.css.map((cssFile) => {
        return fetch(cssFile).then((res) => res.text());
      })
    );

    const styleEl = document.createElement('style');
    styleEl.textContent = cssList.join('\n');

    cache[app.name] = styleEl;

    return styleEl;
  },
};

子应用代码:

// 使用 Shadow DOM 渲染内容
const template = `
  <div class="sub-app">
    <h1>Hello, I am sub app!</h1>
    ...
  </div>`;

shadowDom.innerHTML += template;

// 将样式加入到 Shadow DOM 中
const shadowDom = document.querySelector('.sub-app-container').attachShadow({ mode: 'open' });
shadowDom.appendChild(styleEl);

以上代码中,主应用使用 styleLoader.js 加载子应用的 CSS 文件,并将样式加入到 Shadow DOM 中,从而实现样式隔离。子应用则使用 Shadow DOM 渲染内容,确保不会受到主应用的样式影响。

posted @ 2023-04-25 13:53  阿臻  阅读(1010)  评论(0编辑  收藏  举报