React应用转为自定义元素后styled-components样式未生效如何解决?
问题根因
你已经为MUI的JSS样式指定了Shadow DOM内部的插入点,所以makeStyles定义的样式可以正常注入到Shadow DOM中生效。但styled-components默认会将生成的样式标签插入到全局document.head下,而Shadow DOM的样式隔离机制会屏蔽外部样式,因此styled-components定义的样式无法作用到Shadow DOM内部的元素上。
方案1:调整styled-components配置适配Shadow DOM
如果要继续使用原生styled-components,可按如下步骤调整:
- 确保使用v5.0及以上版本的styled-components,旧版本对Shadow DOM适配能力不足
- 改造
index.tsx代码,为styled-components指定Shadow DOM内部的样式插入点,修改后代码如下:
import React from 'react'; import { render } from 'react-dom'; import App from './App'; import { StylesProvider, jssPreset, } from '@material-ui/core/styles'; import { create } from 'jss'; // 新增导入styled-components的样式管理器 import { StyleSheetManager } from 'styled-components'; class MyWebComponent extends HTMLElement { connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); // MUI JSS插入点 const mountPoint = document.createElement('custom-jss-insertion-point'); shadowRoot.appendChild(mountPoint); // 新增styled-components样式插入点 const styledInsertionPoint = document.createElement('style'); shadowRoot.appendChild(styledInsertionPoint); const jss = create({ ...jssPreset(), insertionPoint: mountPoint, }); render( {/* 新增styled-components样式管理器包裹层 */} <StyleSheetManager target={styledInsertionPoint}> <StylesProvider jss={jss}> <App /> </StylesProvider> </StyleSheetManager>, mountPoint ); } } customElements.define('my-element', MyWebComponent);
调整后styled-components会将所有生成的样式注入到Shadow DOM内部的插入点中,即可正常生效。
方案2:替代方案(亲测可用)
如果不想调整styled-components的配置,可升级到MUI v5,配套使用emotion作为样式方案:
- 升级后可直接使用
@mui/material/styles导出的styled工具替代原生styled-components,API用法和styled-components基本一致,迁移成本低 - 原有的
@mui/styles导出的makeStyles仍可正常使用 - 配置时只需为emotion指定Shadow DOM内部的插入点即可完成适配
内容的提问来源于stack exchange,提问作者snowleopard
相关产品推荐
相关产品推荐

