解決子應(yīng)用樣式覆蓋主應(yīng)用問題:針對不同版本的 Element UI 樣式隔離
在微前端架構(gòu)中,主應(yīng)用和子應(yīng)用可能會使用不同版本的庫和樣式表。尤其是像 Element UI 這樣的 UI 框架,由于版本差異,子應(yīng)用的樣式有可能會影響到主應(yīng)用的 UI,造成樣式?jīng)_突。在這個(gè)場景中,主應(yīng)用使用的是 Element UI 2.6.0 版本,而子應(yīng)用使用的是 Element UI 2.4.4 版本,可能會導(dǎo)致樣式覆蓋問題。具體來說,子應(yīng)用的樣式可能會覆蓋主應(yīng)用的樣式,導(dǎo)致布局錯(cuò)亂。
解決這個(gè)問題的思路是:攔截并禁止子應(yīng)用加載特定的樣式,確保子應(yīng)用的 Element UI 樣式不干擾主應(yīng)用。下面將詳細(xì)介紹如何實(shí)現(xiàn)這一解決方案。
問題分析
當(dāng)子應(yīng)用加載時(shí),它的 Element UI 2.4.4 樣式會與主應(yīng)用的 Element UI 2.6.0 樣式產(chǎn)生沖突,尤其是 theme-chalk 樣式會被插入到 <head> 標(biāo)簽中,導(dǎo)致樣式被覆蓋。為了避免這種情況,我們可以通過監(jiān)聽 head.appendChild 方法,并判斷即將插入的樣式是否為 theme-chalk 樣式,如果是,就拒絕插入。
解決思路
-
攔截樣式插入:通過
Object.defineProperty重新定義document.head.appendChild方法,攔截子應(yīng)用插入的樣式。 -
過濾 Element UI 樣式:檢測插入的樣式標(biāo)簽是否是與 Element UI 相關(guān)的樣式(例如
theme-chalk),如果是,則跳過插入,避免覆蓋主應(yīng)用樣式。 - 保留主應(yīng)用樣式:僅允許主應(yīng)用的樣式正常加載,確保子應(yīng)用的樣式不會污染主應(yīng)用的界面。
實(shí)現(xiàn)代碼
microApp.value = loadMicroApp(
{
name: 'micro-system', // 注冊子應(yīng)用名稱
entry: '//localhost:3335/micro-sys/', // 子應(yīng)用的入口地址
container: renderEl.value, // 子應(yīng)用的掛載容器
},
{
sandbox: {
strictStyleIsolation: false, // 禁用嚴(yán)格樣式隔離
experimentalStyleIsolation: true, // 啟用實(shí)驗(yàn)性樣式隔離
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; // 不插入該樣式
}
// 否則調(diào)用原始的 appendChild 方法,正常插入其他樣式
return originAppendChild.call(this, node);
},
writable: true, // 確保 appendChild 方法是可寫的
configurable: true, // 允許進(jìn)一步修改或刪除該屬性
});
},
}
);
解釋與優(yōu)化
-
攔截
appendChild:- 我們首先保存了原始的
appendChild方法,并在重新定義的方法中進(jìn)行條件判斷。如果待插入的樣式是element-plus/theme-chalk,我們通過return跳過該樣式,不讓它插入到head中。
- 我們首先保存了原始的
-
確保樣式不會影響主應(yīng)用:
- 通過正則匹配樣式的
data-vite-dev-id,我們能準(zhǔn)確識別出子應(yīng)用中的 Element UI 樣式(如theme-chalk),并避免它們影響主應(yīng)用。這樣,即使子應(yīng)用使用了較舊的 Element UI 版本(2.4.4),也不會導(dǎo)致樣式?jīng)_突。
- 通過正則匹配樣式的
-
實(shí)驗(yàn)性樣式隔離:
-
experimentalStyleIsolation開啟后,Qiankun 會嘗試使用實(shí)驗(yàn)性樣式隔離技術(shù),避免子應(yīng)用的樣式污染主應(yīng)用的樣式。
-
注意事項(xiàng)
-
確保樣式隔離:在使用微前端時(shí),除了攔截樣式加載,還可以通過嚴(yán)格的樣式隔離配置(
strictStyleIsolation)來避免樣式污染。 -
調(diào)試和優(yōu)化:在開發(fā)過程中,確保子應(yīng)用和主應(yīng)用的樣式都能正確加載。遇到樣式?jīng)_突時(shí),可以通過
console.log或調(diào)試工具進(jìn)一步分析問題。 - 版本兼容性:盡量確保主應(yīng)用和子應(yīng)用的庫版本兼容,特別是像 Element UI 這樣的 UI 框架,版本差異可能導(dǎo)致更多樣式?jīng)_突。
通過以上方案,您可以有效避免子應(yīng)用的 Element UI 樣式覆蓋主應(yīng)用的樣式,確保微前端架構(gòu)中的樣式互不干擾,從而提高系統(tǒng)的穩(wěn)定性和可維護(hù)性。