如何在React中用Tailwind实现带自定义Props的可复用组件
如何结合Tailwind实现支持自定义颜色和大小的可复用StarRating组件
你的代码里用了stroke-${color}这类动态拼接Tailwind类名的写法,但Tailwind的JIT编译器无法识别动态生成的类名,导致样式不生效。下面提供两种可行方案解决这个问题:
方案1:使用内联style属性(推荐,支持任意颜色值)
这种方式灵活性最高,不管传入的是Tailwind预设颜色名(如black)还是自定义十六进制/RGB颜色,都能直接生效。
修改后的StarRating组件
import { useState } from "react"; import Star from "./Star"; const StarRating = ({ maxRating = 5, textColor = "black", starColor = "#fcc419", // 默认使用黄色星星 emptyStarColor = "black", textSize = "xs", starSize = 5, // 支持数字(对应Tailwind的w/h类)或带单位字符串(如"1.5rem") }) => { const [rating, setRating] = useState(0); const [tempRating, setTempRating] = useState(0); const onRateHandler = (rate) => setRating(rate); const onHoverInHandler = (rate) => setTempRating(rate); const onHoverOutHandler = () => setTempRating(0); return ( <div className="flex flex-row justify-center items-center gap-x-4 p-8"> <div className="flex flex-row justify-center items-center gap-x-3"> {Array.from({ length: maxRating }, (_, i) => ( <Star key={i} onRate={() => onRateHandler(i + 1)} full={tempRating ? tempRating >= i + 1 : rating >= i + 1} hoverIn={() => onHoverInHandler(i + 1)} hoverOut={onHoverOutHandler} starColor={starColor} emptyStarColor={emptyStarColor} size={starSize} /> ))} </div> {/* 用style属性设置文本颜色,支持任意值 */} <p className={`text-${textSize}`} style={{ color: textColor }}> {tempRating || rating || ""} </p> </div> ); }; export default StarRating;
修改后的Star组件
const Star = ({ onRate, full, hoverIn, hoverOut, starColor, emptyStarColor, size }) => { // 处理size:数字对应Tailwind的w/h类,字符串直接用任意值语法 const sizeClass = typeof size === 'number' ? `w-${size} h-${size}` : `w-[${size}] h-[${size}]`; return ( <span role="button" className="cursor-pointer block" onClick={onRate} onMouseEnter={hoverIn} onMouseLeave={hoverOut} > {full ? ( <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" className={sizeClass} style={{ stroke: starColor, fill: starColor }} > <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" /> </svg> ) : ( <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" className={`${sizeClass} fill-none`} style={{ stroke: emptyStarColor }} > <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /> </svg> )} </span> ); }; export default Star;
方案2:使用Tailwind任意值语法(适合熟悉Tailwind规则的场景)
如果想坚持用Tailwind类名,可以用它的任意值语法(如stroke-[#fcc419]),但需要注意以下细节:
修改Star组件的类名部分
// 选中的星星 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" className={`w-${size} h-${size} stroke-[${starColor}] fill-[${starColor}]`} > {/* path内容 */} </svg> // 未选中的星星 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" className={`w-${size} h-${size} fill-none stroke-[${emptyStarColor}]`} > {/* path内容 */} </svg>
补充配置
为了确保动态类名被Tailwind编译,建议在tailwind.config.js中添加安全列表:
module.exports = { safelist: [ { pattern: /stroke-.+/ }, { pattern: /fill-.+/ }, { pattern: /w-.+/ }, { pattern: /h-.+/ }, ], }
使用示例
现在你可以轻松复用这个组件:
// 自定义黄色星星,大小为6,文本颜色为深灰 <StarRating starColor="#fcc419" starSize={6} textColor="gray-700" textSize="sm" /> // 10星评分,蓝色填充星+浅蓝空心星 <StarRating starColor="blue-500" emptyStarColor="blue-200" maxRating={10} />
内容的提问来源于stack exchange,提问作者Mahdieh Honarzadeh
相关产品推荐
相关产品推荐

