我在尝试将动态顺风类分配给react组件时遇到了以下noob问题。
我在tailwind.config.js
中扩展了我的主题颜色如下:
...
theme: {
extend: {
colors: {
blueGray: {
50: '#f6f9f9',
100: '#e4f1f8',
200: '#c2e0f0',
300: '#91c0db',
400: '#5b9bbf',
500: '#4479a3',
600: '#385f87',
700: '#2d4768',
800: '#203049',
900: '#131d2f',
},
// OTHER COLORS
},
},
},
...
我的反应组件如下:
import Draggable from 'react-draggable';
type SensorProps = {
name: string
color: string
}
export default function Sensor(props : SensorProps): JSX.Element {
return (
<Draggable
axis="both"
bounds="flow-canvas">
<div className={`border-${props.color}-400 bg-${props.color}-50 text-${props.color}-700`}>
<p> {props.name} </p>
</div>
</Draggable>
)
}
以下是我如何实例化传感器组件的一些示例
<Sensor name={"Water Level"} color={"blueGray"} />
<Sensor name={"Flow"} color={"mGreen"} />
问题是没有应用这些类,但当我检查页面时,div有正确的类。
如果切换自:
<div className={`border-${props.color}-400 bg-${props.color}-50 text-${props.color}-700`}>
至:
<div className={`border-blueGray-400 bg-blueGray-50 text-blueGray-700`}>
它起作用:(
我已经在使用顺风JIT编译器
...
mode: 'jit',
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
...
有什么建议吗?
顺风编译器在编译时解析代码,并清除它认为在任何地方都没有使用的类。您没有直接使用border-blueGray-400
,因此它将其视为未使用的类,并将其从捆绑包中删除以提高性能。
在我看来,最好的解决方案是不传递任意的道具,如color
、size
等,而是传递className
属性。
因此,您可以这样呈现您的组件:
<Sensor className="border-blueGray-400 bg-blueGray-50 text-blueGray-700" />
在子组件中:
<div className={props.className} />
现在您可以使用
<div className={`border-${props.color}-400 bg-${props.color}-50 text-${props.color}-700`}>
通过在tailwindcss 中使用安全列表类
说明
是否建议在tailwind
中使用dynamic class
否
通常不建议在tailwind-css
中使用dynamic classes
,因为tailwind
使用tree-shaking
,即任何未在源文件中声明的类都不会在输出文件中生成。
因此,始终建议使用完整类名
根据文件
如果使用字符串插值或将部分类名连接在一起,Tailwind将找不到它们,因此不会生成相应的CSS
周围没有工作吗
是
作为最后的手段,Tailwind提供安全登录课程。
安全列表是最后的手段,只应在无法扫描某些内容以查找类名的情况下使用。这种情况很少见,您几乎永远都不需要此功能。
在您的示例中,您希望有100 500 700
色调的颜色。可以使用正则表达式来包含使用pattern
所需的所有颜色,并相应地指定阴影。
在tailwind.config.js
中
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
{
pattern: /bg-(red|green|blue|orange)-(100|500|700)/, // You can display all the colors that you need
},
],
// ...
}
额外:如何自动在safelist
中拥有所有顺风颜色const tailwindColors = require("./node_modules/tailwindcss/colors")
const colorSafeList = []
// Skip these to avoid a load of deprecated warnings when tailwind starts up
const deprecated = ["lightBlue", "warmGray", "trueGray", "coolGray", "blueGray"]
for (const colorName in tailwindColors) {
if (deprecated.includes(colorName)) {
continue
}
// Define all of your desired shades
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]
const pallette = tailwindColors[colorName]
if (typeof pallette === "object") {
shades.forEach((shade) => {
if (shade in pallette) {
colorSafeList.push(`text-${colorName}-${shade}`)
colorSafeList.push(`bg-${colorName}-${shade}`)
colorSafeList.push(`border-${colorName}-${shade}`)
}
})
}
}
// tailwind.config.js
module.exports = {
safelist: colorSafeList, // <-- add the safelist here
content: ["{pages,app}/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: tailwindColors,
},
},
plugins: [],
}
使用内联CSS
当我动态生成具有相同设计但不同文本和按钮颜色的jsx时,我偶然发现了这个问题。这可能有点棘手,因为在开发时,它看起来很好,所有的类都正确呈现,但快速重新启动dev-server似乎可以从最终捆绑包中完全删除这些类。诅咒git几分钟后,我有了直觉,发现了这条线索。
对于任何未来的读者来说,在不使用外部库和safelisting
顺风类膨胀风险的情况下,最优雅的解决方案是使用内联样式,即style = {{ color: INSERT_VARIABLE_HERE }}
,您可以继续使用。
工作代码:
// Generate modals for different types
// All use the same design
// IMPORTANT: Tailwind cannot deduce partial class names sent as arguments, and
// removes them from final bundle, safe to use inline styling
const _generateModal = (
initialTitle: string,
image: string,
buttonColor: string,
bgColor: string = "white",
textColor: string = "rgb(55 65 81)",
buttonText: string = "Continue"
) => {
return ({ title = initialTitle, text, isOpen, onClose }: Props) => {
if (!isOpen) return null;
return ReactDom.createPortal(
<div className="fixed inset-0 bg-black bg-opacity-80">
<div className="flex h-full flex-col items-center justify-center">
<div
className={`relative flex h-1/2 w-1/2 flex-col items-center justify-evenly rounded-xl lg:w-1/4`}
style={{ color: textColor, backgroundColor: bgColor }}
>
<RxCross2
className="absolute top-0 right-0 mr-5 mt-5 cursor-pointer text-2xl"
onClick={() => onClose()}
/>
<h1 className="text-center text-3xl font-thin">{title}</h1>
<h3 className="text-center text-xl font-light tracking-wider opacity-80">
{text}
</h3>
<img
src={image}
alt="info image"
className="hidden w-1/6 lg:block lg:w-1/4"
/>
<button
onClick={() => onClose()}
className={`rounded-full px-16 py-2 text-xl text-white`}
style={{ backgroundColor: buttonColor }}
>
{buttonText}
</button>
</div>
</div>
</div>,
document.getElementById("modal-root") as HTMLElement
);
};
};
export const SuccessModal = _generateModal(
"Success!",
checkimg,
"rgb(21 128 61)" // green-700
);
export const InfoModal = _generateModal(
"Hey there!",
infoimg,
"rgb(59 130 246)" // blue-500
);
export const ErrorModal = _generateModal(
"Face-plant!",
errorimg,
"rgb(190 18 60)", // rose-700
"rgb(225 29 72)", // rose-600
"rgb(229 231 235)", // gray-200
"Try Again"
);
我在这里使用reactjs和typescript,这里的代码可以用来生成3种类型的弹出模式,InfoModal
、ErrorModal
和SuccessModal
。jsx生成器可以通过为我们编写代码来帮助缓解这些问题,而不是在任何地方都编写相同的样板代码,其中更新一个代码需要在3个地方进行更新
您可以使用clsx这样的库有条件地呈现类。然后您的子组件将呈现:
<div className={clsx(
"border-blueGray-400 bg-blueGray-50 text-blueGray-700": props.color === "blueGray",
"border-mGray-400 bg-mGray-50 text-mGray-700": props.color === "mGray",
)} />
如果您只想修改一个或两个属性,这不是一个好的解决方案。然后我建议直接通过顺风课程作为道具,就像另一个答案中提到的那样。
但是,如果您有一些更复杂的逻辑,比如依赖于类的多个css属性,这个解决方案可能是好的。