MUI v5插入Shadow DOM样式时Select下拉选项样式与点击事件异常
请注意本内容针对MUI v5版本的
@mui/material,不适用于v4版本的@material-ui/core
问题根因
MUI的Select组件下拉菜单底层基于Popover组件实现,默认会将弹窗DOM挂载到全局document.body节点,不在你创建的Shadow DOM作用域内,因此你配置的Emotion样式缓存、JSS插入点均无法对下拉菜单生效,同时事件冒泡会受Shadow DOM边界阻隔,导致点击交互异常。
修复方案
你需要修改Popover的默认挂载容器,指定其挂载到你的Shadow DOM内部节点,有两种实现方式:
方式1:单组件单独配置
在使用Select组件时,通过MenuProps指定挂载容器为当前Shadow DOM内的节点:
// Demo组件内Select的用法示例 <Select labelId="demo-simple-select-label" id="demo-simple-select" value={age} label="Age" onChange={handleChange} // 新增以下配置 MenuProps={{ container: document.querySelector('my-element').shadowRoot.querySelector('div') }} > {/* 下拉选项代码 */} </Select>
方式2:全局主题统一配置(推荐)
在创建Theme的时候统一配置Popover的默认容器,避免每个Select单独修改,修改后的完整代码如下:
import React from 'react'; import Demo from './demo'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import { StylesProvider, jssPreset } from '@mui/styles'; import { CacheProvider } from '@emotion/react'; import createCache from '@emotion/cache'; import { create } from 'jss'; import { render } from 'react-dom'; // 新增:全局存储Shadow DOM挂载节点 let shadowMountNode = null; const theme = createTheme({ // 新增:全局配置Popover默认挂载容器 components: { MuiPopover: { defaultProps: { container: () => shadowMountNode } } } }); class MyWebComponent extends HTMLElement { connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); const emotionRoot = document.createElement('style'); const mountPoint = document.createElement('div'); shadowRoot.appendChild(emotionRoot); const reactRoot = shadowRoot.appendChild(mountPoint); // 新增:将挂载节点赋值给全局变量 shadowMountNode = reactRoot; const jss = create({ ...jssPreset(), insertionPoint: reactRoot, }); const cache = createCache({ key: 'css', prepend: true, container: emotionRoot, }); render( <StylesProvider jss={jss}> <CacheProvider value={cache}> <ThemeProvider theme={theme}> <Demo /> </ThemeProvider> </CacheProvider> </StylesProvider>, mountPoint ); } } if (!customElements.get('my-element')) { customElements.define('my-element', MyWebComponent); }
内容的提问来源于stack exchange,提问作者snowleopard
相关产品推荐
相关产品推荐

