You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:39:00