Shadow DOM
Shadow DOM 允许你封装应用程序的各个部分,使其与针对常规 DOM 树的全局样式分隔开。
如何在 Material UI 中使用 Shadow DOM
1. 样式
Shadow DOM 是一种 API,它提供了一种将隐藏的、隔离的 DOM 附加到元素的方法。当您需要将不同组件的结构、样式和行为与页面上其余代码分开,以防止冲突时,这非常有用。请参阅 关于 Shadow DOM 的 MDN 文档 以获取更多信息。以下代码片段展示了如何在 Shadow 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
。但是由于样式仅在 Shadow DOM 内部应用,因此我们需要在 Shadow DOM 容器内部渲染 portal
const theme = createTheme({
components: {
MuiPopover: {
defaultProps: {
container: shadowRootElement,
},
},
MuiPopper: {
defaultProps: {
container: shadowRootElement,
},
},
MuiModal: {
defaultProps: {
container: shadowRootElement,
},
},
},
});
// ...
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>;
3. CSS 主题变量(可选)
要在 Shadow DOM 内部使用 CSS 主题变量,您需要设置用于生成 CSS 变量的选择器
const theme = createTheme({
+ cssVariables: {
+ rootSelector: ':host',
+ colorSchemeSelector: 'class',
+ },
components: {
// ...same as above steps
}
})
最后,使用步骤 1 中的 shadowRootElement
作为值,设置 colorSchemeNode
属性
<ThemeProvider
theme={theme}
+ colorSchemeNode={shadowRootElement}
>
演示
在下面的示例中,您可以看到 shadow DOM 外部的组件受全局样式影响,而 shadow DOM 内部的组件则不受影响