当我想从样式化组件迁移到 CSS 模块时,出现了以下问题。
假设我有以下样式组件,它接受动态参数
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
组件?
这可能是一种与你以前不同的思维方式,但它可以工作
style={{ [`--offset`]: `${offset}px` }}
.item {
margin-left: var(--offset);
}
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
}`}
style={{ [`--offset`]: `${offset}px` }}
>
{children}
</li>
);
};
演示:https://codesandbox.io/s/styledcomponent-to-css-modules-1kbqx
对于 1,我同意 @Mosh 只使用 style 属性。 CSS 模块在设计上是静态的,否则无法完成此操作(我认为样式组件也使用 style 属性,因此您不会丢失任何东西)。
对于 2,您可以利用 Sass 模块,它允许您在一个位置定义主题并根据需要导入它们:
/theme/_colors.scss
$red: rgb(200, 0 50);
/components/Item.module.scss
@import "../theme/colors"
.selected {
background: $red;
}
注意:如果您使用 Create React App 绝对路径,您可以从 root 导入为
~theme/colors