【问题标题】:Dynamic CSS in CSS Modules when coming from Styled Components来自样式化组件时 CSS 模块中的动态 CSS
【发布时间】:2021-09-21 14:23:44
【问题描述】:

当我想从 Styled Components 迁移到 CSS Modules 时,出现了以下问题。

假设我有以下样式组件,它接受动态参数 offset 和动态 CSS 字符串 theme

const Li = styled.li`
  &.selected {
    background-color: grey;
  }

  margin-left: ${({ offset }) => offset}px;

  ${({ theme }) => theme};
`;

在我的代码中,我会按以下方式使用它:

const Parent = () => (
  <List>
    {list.map((item) => (
      <Item
        key={item.id}
        id={item.id}
        selectedIds={[]}
        offset={24}
        theme={`
          &.selected {
            background-color: green;
          }
        `}
      >
        {item.name}
      </Item>
    ))}
  </List>
);

const Item = ({ id, offset = 0, theme, children }) => {
  return (
    <Li
      theme={theme}
      offset={offset}
      className={selectedIds.includes(id) && 'selected'}
    >
      {children}
    </Li>
  );
};

要求:现在我真的会保留Item 的组件API:传递number 偏移量和样式字符串theme。所以基本上Parent 组件中的所有内容都应该保持这种状态。

如何在内部转换 Item 组件以使用 CSS 模块而不是样式化的 Li 组件?

【问题讨论】:

    标签: css reactjs styled-components css-modules


    【解决方案1】:

    这可能是一种不同于你以前的思维方式,但它可以工作

    1. 您可以使用 css 变量
    style={{ [`--offset`]: `${offset}px` }}
    
    .item {
      margin-left: var(--offset);
    }
    
    1. 您可以拥有一个专用于主题的 css 模块(文件)。在你的情况下,它有withSelected
    .withSelected {
      &.selected {
        background-color: green;
      }
    }
    

    所以你可以将它作为“主题”传递

    theme={themes.withSelected}
    

    这就是组件的外观

    import styles from "./style.module.scss";
    import themes from "./themes.module.scss";
    
    const Parent = () => (
      <ul>
        {list.map((item) => (
          <Item
            key={item.id}
            id={item.id}
            selectedIds={[1]}
            offset={24}
            theme={themes.withSelected}
          >
            {item.name}
          </Item>
        ))}
      </ul>
    );
    
    const Item = ({ id, offset = 0, theme, children, selectedIds }) => {
      return (
        <li
          className={`${styles.item} ${theme} ${
            selectedIds.includes(id) && themes.selected
          }`}
          theme={theme}
          style={{ [`--offset`]: `${offset}px` }}
        >
          {children}
        </li>
      );
    };
    

    演示:https://codesandbox.io/s/styledcomponent-to-css-modules-1kbqx

    【讨论】:

    • 感谢莫什的回答! 1. 解决方案将是一个很好的方法!对于 2.,我期望比必须使用 CSS 模块将其作为主题传递更模棱两可。我想将它作为样式字符串传递,就像我在问题中所做的那样。那么如何在 Item 组件中获取它呢?
    • 编辑了问题以更多地反映我想在这里实现的目标。
    • 可以将 css 作为 prop 传递的好处是(我不确定它的可扩展性如何)。但是,styledComponents(“SC”)的区别之一是涉及到 js,因此您可以在运行时操作样式。因此 SC 为您提供 (1) 运行时操作 (2) css 范围。像 vanilla css 这样的 css-modules 是静态的,只为您提供 css 作用域。这就是为什么当你从 SC 迁移到 css-modules 时需要一种新的、实际上是旧的)思维方式。
    【解决方案2】:

    对于 1,我同意 @Mosh 仅使用 style 属性。 Css 模块在设计上是静态的,否则无法完成(我认为 styled-components 也使用 style 属性,因此您不会丢失任何东西)。

    对于 2,您可以利用 Sass 模块,它允许您在一个地方定义您的主题并根据需要导入它们:

    /theme/_colors.scss

    $red: rgb(200, 0 50);
    

    /components/Item.module.scss

    @import "../theme/colors"
    
    .selected {
        background: $red;
    }
    

    注意:如果您使用Create React App absolute paths,您可以从根目录导入~theme/colors

    【讨论】:

      猜你喜欢
      • 2020-02-13
      • 2019-11-13
      • 2021-04-03
      • 2019-12-18
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      • 2017-07-10
      • 2021-10-21
      相关资源
      最近更新 更多