我正在研究一个反应钩子,它将根据传递给组件的道具从 (s)css 模块加载样式。它看起来像这样:
import { useState, useEffect } from 'react';
export type SCSSModule = Record<string, string>;
export type Styles = Record<string, any>;
export default function useStyles(scssModule: SCSSModule, styles: Styles): string {
const [className, setClassName] = useState<string>('');
useEffect(() => {
const classNames: string[] = [];
for (const k in styles) {
const attrSelector = `[${k}='${styles[k]}']`;
if (k in scssModule) {
classNames.push(scssModule[k]);
} else if (attrSelector in scssModule) {
classNames.push(scssModule[attrSelector]);
} else {
throw new Error(`Missing style for ${k}=${styles[k]}`);
}
setClassName(classNames.join(' '));
}
}, [styles]);
return className;
}
理论上,我希望我们能够像这样编写一个 (S)CSS 模块:
.grid {
display: grid;
}
[gutter='small'] {
grid-gap: 8px;
}
[gutter='medium'] {
grid-gap: 16px;
}
[gutter='large'] {
grid-gap: 24px;
}
[columns='1'] {
grid-template-columns: repeat(1, 1fr);
}
[columns='2'] {
grid-template-columns: repeat(2, 1fr);
}
[columns='3'] {
grid-template-columns: repeat(3, 1fr);
}
并且能够像这样使用钩子:
import styles from "./Grid.module.scss"
import useStyles from "../hooks/useStyles"
import type { FC } from "react";
const { grid } = styles;
interface GridProps {
gutter?: "small" | "medium" | "large";
columns?: number;
}
const Grid: FC<GridProps> = ({ gutter, columns, children }) => {
const className = useStyles(styles, { grid, gutter, columns });
return <div className={className}>{ children }</div>
}
这应该做的是根据模式从 css 模块加载样式:
- 对于每个传递的键,看看是否有一个完全匹配的键,然后加载它的样式,这样你就可以直接加载样式
- 对于传递给钩子的每个键/值(prop),加载样式
[propName='propValue']
不过,我似乎无法像[columns='1'] {}
从 CSS 模块加载定义。
我知道,我可以更改模式,而不是定义道具的样式,因为[propName='propValue'] {}
我可以将它们定义为.propName-propValue {}
或其他东西,但我想看看是否可以以任何方式使用[propName='propValue'] {}
语法。
你有办法做到这一点吗?