跳到主要內容
+

陰影 DOM

陰影 DOM 讓您可以封裝應用程式的各個部分,使其與目標為一般 DOM 樹狀結構的全域樣式隔離。

如何在 Material UI 中使用陰影 DOM

1. 樣式

陰影 DOM 是一個 API,提供將隱藏且分離的 DOM 附加到元素的方法。當您需要將不同元件的結構、樣式和行為與頁面上其餘程式碼分離,以防止衝突時,這非常有用。請參閱 MDN 文件中有關陰影 DOM 的說明 以取得更多資訊。以下程式碼片段示範如何在陰影 DOM 內部套用樣式

const container = document.querySelector('#root');
const shadowContainer = container.attachShadow({ mode: 'open' });
const shadowRootElement = document.createElement('div');
shadowContainer.appendChild(shadowRootElement);

const cache = createCache({
  key: 'css',
  prepend: true,
  container: shadowContainer,
});

ReactDOM.createRoot(shadowRootElement).render(
  <CacheProvider value={cache}>
    <App />
  </CacheProvider>,
);

2. 主題

Material UI 元件(如 Menu、Dialog、Popover 等)使用 MUI Base Portal 元件在目前 DOM 階層外部的容器中呈現新的「子樹狀結構」。預設情況下,此容器是 document.body。但是由於樣式僅在陰影 DOM 內部套用,因此我們也需要在陰影 DOM 容器內部呈現入口

const theme = createTheme({
  components: {
    MuiPopover: {
      defaultProps: {
        container: shadowRootElement,
      },
    },
    MuiPopper: {
      defaultProps: {
        container: shadowRootElement,
      },
    },
    MuiModal: {
      defaultProps: {
        container: shadowRootElement,
      },
    },
  },
});

// ...

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>;

3. CSS 主題變數(選用)

若要在陰影 DOM 內部使用 CSS 主題變數,您需要設定選取器以產生 CSS 變數

 const theme = createTheme({
+  cssVariables: {
+    rootSelector: ':host',
+    colorSchemeSelector: 'class',
+  },
   components: {
     // ...same as above steps
   }
 })

最後,使用步驟 1 中的 shadowRootElement 作為值,設定 colorSchemeNode 屬性

 <ThemeProvider
   theme={theme}
+  colorSchemeNode={shadowRootElement}
 >

示範

在以下範例中,您可以看到陰影 DOM 外部的元件受到全域樣式的影響,而陰影 DOM 內部的元件則不受影響