这里非常基本的问题。
我正在尝试开始学习 React,我对处理这种事情的最佳设计模式感到好奇。
我有一个按钮组件,我想要应用不同类的组件的"主要"和"次要"变体。 以下情况是最好的方法吗?我正在传递一个"变体"道具,用于定义要使用的按钮。
如果这不是最好的解决方案,如果我想要特定组件的"变体"会是什么。
谢谢!
class Button extends Component {
render() {
// --- SECONDARY BUTTON --- //
if(this.props.variant == 'secondary') {
return (
<div className = 'button-wrapper secondary'>
<div className = 'button'>
{this.props.text}
</div>
</div>
);
// --- PRIMARY BUTTON --- //
}else if(this.props.variant == 'primary') {
return (
<div className = 'button-wrapper primary'>
<div className = 'button'>
{this.props.text}
</div>
</div>
);
}
}
}
如果你的区别只在className
,也许你可以通过以下方式实现同样的目标:
render() {
const { variant } = this.props;
return (
<div className = {`button-wrapper ${ variant === 'secondary' ? '' : 'primary' }`}>
<div className = 'button'>
{this.props.text}
</div>
</div>
);
我建议使用一些 npm 包来处理这类事情,因为它们会因组件而异,你最终会在组件中放置许多丑陋的 if-else 语句。你可以通过创建一个接受 props 并返回最终一组类的钩子来获得它,但这又是一个丑陋的钩子。
你应该尝试一下 npm pkg@vtechguys/vs
.
import { GetVariantProps, vs } from "@vtechguys/vs";
export const button = vs({
// Example with Tailwind rich classes
base: ["font-semibold", "border", "rounded"],
variants: {
intent: {
color: [
"bg-blue-500",
"text-white",
"border-transparent",
"hover:bg-blue-600"
],
secondary: [
"bg-white",
"text-gray-800",
"border-gray-400",
"hover:bg-gray-100"
]
},
size: {
small: ["text-sm", "py-1", "px-2"],
medium: ["text-base", "py-2", "px-4"]
}
},
defaultVariants: {
intent: "primary",
size: "medium"
}
});
export type ButtonVariantProps = GetVariantProps<typeof button>;
不是可以简单地用作
import React from "react";
type ButtonOwnProps = {
// ... some button props ...
};
type ButtonProps = React.PropsWithChildren<ButtonVariantProps & ButtonOwnProps>;
export function ButtonTailwind(props: ButtonProps) {
const { color, size, children, ...rest } = props;
// you can event extract it in a hook to make it more clean
const variants = button({ color, size });
// Applicable Tailwind classes
const classes = clsx(variants);
return (
<button className={classes} {...rest}>
{children}
</button>
);
}