如何使用样式组件覆盖 ExpansionPanelSummary 深层元素?

Posted

技术标签:

【中文标题】如何使用样式组件覆盖 ExpansionPanelSummary 深层元素?【英文标题】:How can I override ExpansionPanelSummary deep elements with styled-components? 【发布时间】:2019-08-20 22:48:27 【问题描述】:

使用the docs/examples 来覆盖带有样式组件的Material UI 样式,我设法在ExpansionPanelExpansionPanelDetails 中设置了根和“更深层元素”的样式。

但是,当我使用相同的技术从传递给 styled() 的函数中返回覆盖的 ExpansionPanelSummary 时,ExpansionPanelSummary 在 DOM 中移动,整个 ExpansionPanel 不再正确呈现。

有问题的技术,应用于ExpansionPanel(这在容器ExpansionPanel 上按预期工作):

import MUIExpansionPanel from '@material-ui/core/ExpansionPanel';

export const ExpansionPanel = styled(props => (
  <MUIExpansionPanel
    classes=expanded: 'expanded'
    ...props
  />
))`
  && 
    ...root style overrides
  
  &&.expanded 
    ...expanded style overrides
  
`;

ExpansionPanel 和朋友的典型 DOM(类名缩写):

<div class="MuiExpansionPanel...">
  <div class="MuiExpansionPanelSummary..." />
  <div class="MuiCollapse-container...>
    <div class="MuiCollapse-wrapper...>
      <div class="MuiCollapse-wrapperInner...>
        <div class="MuiExpansionPanelDetails..." />
      </div>
    </div>
  </div>
</div>

当我将上述技术应用于ExpansionPanelSummary时的DOM:

<div class="MuiExpansionPanel...">
  <div class="MuiCollapse-container...>
    <div class="MuiCollapse-wrapper...>
      <div class="MuiCollapse-wrapperInner...>
        <div class="MuiExpansionPanelSummary..." />
        <div class="MuiExpansionPanelDetails..." />
      </div>
    </div>
  </div>
</div>

为了完整起见,这是我对ExpansionPanelSummary 所做的事情的最小复制,它触发了 DOM 切换:

export const ExpansionPanelSummary = styled(props => (
  <MUIExpansionPanelSummary
    ...props
  />
))``;

我的 JSX 是标准的 ExpansionPanel 设置:

<ExpansionPanel>
  <ExpansionPanelSummary>
    Summary Label
  </ExpansionPanelSummary>
  <ExpansionPanelDetails>
    <div>Some Content</div>
  </ExpansionPanelDetails>
</ExpansionPanel>

【问题讨论】:

【参考方案1】:

这个困难与使用样式组件无关,只是与将 ExpansionPanelSummary 包装在另一个组件中有关。

您可以类似地使用ExpansionPanelSummary 的以下包装来重现此内容:

const MyCustomSummary = props => 
  return (
    <ExpansionPanelSummary ...props expandIcon=<ExpandMoreIcon />>
      <Typography>props.text</Typography>
    </ExpansionPanelSummary>
  );
;

有几个像这样的组件组,其中 Material-UI 父组件查找特定类型的子组件并特别对待该子组件。例如,您可以在ExpansionPanel中找到以下块

      if (isMuiElement(child, ['ExpansionPanelSummary'])) 
        summary = React.cloneElement(child, 
          disabled,
          expanded,
          onChange: this.handleChange,
        );
        return null;
      

幸运的是,Material-UI 有一种直接的方式来告诉它,您的自定义组件应该通过muiName 属性与特定的 Material-UI 组件一样对待:

MyCustomSummary.muiName = "ExpansionPanelSummary";

或者在你的情况下它看起来像:

export const ExpansionPanelSummary = styled(props => (
  <MUIExpansionPanelSummary
    ...props
  />
))``;

ExpansionPanelSummary.muiName = "ExpansionPanelSummary";

【讨论】:

该死的,它有效。我的下一步是开始在源头中四处寻找……但那是星期五下午 5 点。感谢您为我做侦探工作! 我使用的是TypeScript,所以我发现我需要做(MyCustomSummary as any).muiName = "ExpansionPanelSummary";,因为来自withSyles(...styles)(ExpansionPanelSummary)的类型似乎不包括muiName,但在那之后它就可以工作了!

以上是关于如何使用样式组件覆盖 ExpansionPanelSummary 深层元素?的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js 如何在组件中定义(覆盖)css 样式?

如何从祖先覆盖嵌套 Material UI 组件的样式?

如何覆盖prime-react组件CSS样式?

如何在scoped不污染组件样式的前提下,实现el-input组件样式覆盖?

如何在不使用 MUIThemeProvider 的情况下覆盖 material-ui TextField 组件的样式?

选中后如何覆盖 Material-UI 开关组件的样式?