qiankun解决主应用和子应用使用不同element-plus
2024-12-10 本文已影响0人
lihao_李浩
解决子应用样式覆盖主应用问题:针对不同版本的 Element UI 样式隔离
在微前端架构中,主应用和子应用可能会使用不同版本的库和样式表。尤其是像 Element UI 这样的 UI 框架,由于版本差异,子应用的样式有可能会影响到主应用的 UI,造成样式冲突。在这个场景中,主应用使用的是 Element UI 2.6.0 版本,而子应用使用的是 Element UI 2.4.4 版本,可能会导致样式覆盖问题。具体来说,子应用的样式可能会覆盖主应用的样式,导致布局错乱。
解决这个问题的思路是:拦截并禁止子应用加载特定的样式,确保子应用的 Element UI 样式不干扰主应用。下面将详细介绍如何实现这一解决方案。
问题分析
当子应用加载时,它的 Element UI 2.4.4 样式会与主应用的 Element UI 2.6.0 样式产生冲突,尤其是 theme-chalk
样式会被插入到 <head>
标签中,导致样式被覆盖。为了避免这种情况,我们可以通过监听 head.appendChild
方法,并判断即将插入的样式是否为 theme-chalk
样式,如果是,就拒绝插入。
解决思路
-
拦截样式插入:通过
Object.defineProperty
重新定义document.head.appendChild
方法,拦截子应用插入的样式。 -
过滤 Element UI 样式:检测插入的样式标签是否是与 Element UI 相关的样式(例如
theme-chalk
),如果是,则跳过插入,避免覆盖主应用样式。 - 保留主应用样式:仅允许主应用的样式正常加载,确保子应用的样式不会污染主应用的界面。
实现代码
microApp.value = loadMicroApp(
{
name: 'micro-system', // 注册子应用名称
entry: '//localhost:3335/micro-sys/', // 子应用的入口地址
container: renderEl.value, // 子应用的挂载容器
},
{
sandbox: {
strictStyleIsolation: false, // 禁用严格样式隔离
experimentalStyleIsolation: true, // 启用实验性样式隔离
speedy: true, // 提升样式加载速度
},
},
{
async afterMount(app, global) {
const originAppendChild = global.document.head.appendChild;
// 重新定义 document.head.appendChild 方法,拦截样式的插入
Object.defineProperty(global.document.head, 'appendChild', {
value(node: Element) {
const dataId = node?.getAttribute('data-vite-dev-id');
// 如果插入的样式是 Element UI 的 theme-chalk 样式,则跳过
if (dataId && /element-plus\/theme-chalk/.test(dataId)) {
return; // 不插入该样式
}
// 否则调用原始的 appendChild 方法,正常插入其他样式
return originAppendChild.call(this, node);
},
writable: true, // 确保 appendChild 方法是可写的
configurable: true, // 允许进一步修改或删除该属性
});
},
}
);
解释与优化
-
拦截
appendChild
:- 我们首先保存了原始的
appendChild
方法,并在重新定义的方法中进行条件判断。如果待插入的样式是element-plus/theme-chalk
,我们通过return
跳过该样式,不让它插入到head
中。
- 我们首先保存了原始的
-
确保样式不会影响主应用:
- 通过正则匹配样式的
data-vite-dev-id
,我们能准确识别出子应用中的 Element UI 样式(如theme-chalk
),并避免它们影响主应用。这样,即使子应用使用了较旧的 Element UI 版本(2.4.4),也不会导致样式冲突。
- 通过正则匹配样式的
-
实验性样式隔离:
-
experimentalStyleIsolation
开启后,Qiankun 会尝试使用实验性样式隔离技术,避免子应用的样式污染主应用的样式。
-
注意事项
-
确保样式隔离:在使用微前端时,除了拦截样式加载,还可以通过严格的样式隔离配置(
strictStyleIsolation
)来避免样式污染。 -
调试和优化:在开发过程中,确保子应用和主应用的样式都能正确加载。遇到样式冲突时,可以通过
console.log
或调试工具进一步分析问题。 - 版本兼容性:尽量确保主应用和子应用的库版本兼容,特别是像 Element UI 这样的 UI 框架,版本差异可能导致更多样式冲突。
通过以上方案,您可以有效避免子应用的 Element UI 样式覆盖主应用的样式,确保微前端架构中的样式互不干扰,从而提高系统的稳定性和可维护性。