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 渲染内容,确保不会受到主应用的样式影响。