在 TailwindCss 中动态构建类名
Dynamically build classnames in TailwindCss
我目前正在使用 TailwindCss 为我的下一个项目构建组件库,我只是 运行 在处理 Button 组件时遇到了一个小问题。
我正在传递 'primary'
或 'secondary'
之类的道具,它与我在 tailwind.config.js
中指定的颜色相匹配,然后我想将其分配给按钮组件使用Template literals
像这样:bg-${color}-500
<button
className={`
w-40 rounded-lg p-3 m-2 font-bold transition-all duration-100 border-2 active:scale-[0.98]
bg-${color}-500 `}
onClick={onClick}
type="button"
tabIndex={0}
>
{children}
</button>
class 名称在浏览器中显示正常,它在 DOM 中显示 bg-primary-500
,但在应用的样式选项卡中不显示。
主题配置如下:
theme: {
extend: {
colors: {
primary: {
500: '#B76B3F',
},
secondary: {
500: '#344055',
},
},
},
},
但它不应用任何样式。如果我只是手动添加 bg-primary-500
它工作正常。
老实说,我只是想知道这是不是因为 JIT 编译器没有选择动态 class 名称,或者我做错了什么(或者这不是使用 tailWind 的方式) .
欢迎任何帮助,提前致谢!
这种编写 Tailwind 的方式 CSS classes is not recommended. Even JIT mode doesn't 支持它,引用 Tailwind CSS 文档:“Tailwind 不包括任何类型的客户端运行时,因此 class 名称需要在构建时静态提取,并且不能依赖于在客户端更改的任何类型的任意动态值"
所以在发现不推荐这种工作方式并且JIT不支持它之后(感谢慷慨的评论者)。我已将方法更改为更基于 'config' 的方法。
基本上,我为不同的道具定义了一个具有基本配置的常量,并将它们应用于组件。维护工作多了一点,但它完成了工作。
这是一个配置示例。 (目前无需打字)并准备进行一些更好的重构,但您会明白的。
const buttonConfig = {
// Colors
primary: {
bgColor: 'bg-primary-500',
color: 'text-white',
outline:
'border-primary-500 text-primary-500 bg-opacity-0 hover:bg-opacity-10',
},
secondary: {
bgColor: 'bg-secondary-500',
color: 'text-white',
outline:
'border-secondary-500 text-secondary-500 bg-opacity-0 hover:bg-opacity-10',
},
// Sizes
small: 'px-3 py-2',
medium: 'px-4 py-2',
large: 'px-5 py-2',
};
然后我就这样应用样式:
<motion.button
whileTap={{ scale: 0.98 }}
className={`
rounded-lg font-bold transition-all duration-100 border-2 focus:outline-none
${buttonConfig[size]}
${outlined && buttonConfig[color].outline}
${buttonConfig[color].bgColor} ${buttonConfig[color].color}`}
onClick={onClick}
type="button"
tabIndex={0}
>
{children}
</motion.button>
对于 tailwind JIT
模式或使用 JIT
的 v3,您必须确保导出对象样式的文件包含在 tailwind.config.js
的内容选项中,例如
content: ["./src/styles/**/*.{html,js}"],
在 v3 中,正如 Blessing 所说,您可以更改内容数组以支持它。
我有这个
const PokemonTypeMap = {
ghost: {
classes: "bg-purple-900 text-white",
text: "fantasma",
},
normal: {
classes: "bg-gray-500 text-white",
text: "normal",
},
dark: {
classes: "bg-black text-white",
text: "siniestro",
},
psychic: {
classes: "bg-[#fc46aa] text-white",
text: "psíquico",
},
};
function PokemonType(props) {
const pokemonType = PokemonTypeMap[props.type];
return (
<span
className={pokemonType.classes + " p-1 px-3 rounded-3xl leading-6 lowercase text-sm font-['Open_Sans'] italic"}
>
{pokemonType.text}
</span>
);
}
export default PokemonType;
类似于你的方法,然后我将数组移动到一个 JSON 文件,它认为工作正常,但是是浏览器缓存......所以按照 Blessing 的回应,你可以添加 .json像这样
content: ["./src/**/*.{js,jsx,ts,tsx,json}"],
终于有了这段代码,我认为它更好。
import PokemonTypeMap from "./pokemonTypeMap.json";
function PokemonType(props) {
const pokemonType = PokemonTypeMap[props.type];
return (
<span className={pokemonType.classes + " p-1 px-3 rounded-3xl leading-6 lowercase text-sm font-['Open_Sans']"}>
{pokemonType.text}
</span>
);
}
export default PokemonType;
正如有人在此线程中所说,TailWindCSS 3 不支持 动态 class 名称(参见 https://tailwindcss.com/docs/content-configuration#dynamic-class-names)。
我使用 “安全列表” 功能从清除中排除了一些 class 名称。在 tailwind.config.js 你可以使用纯 JS 来开发这样的东西:(它有点 hacky,我同意)
const colors = require('./node_modules/tailwindcss/colors');
const colorSaveList = [];
const extendeColors = {};
for (const key in colors) {
extendeColors[key] = colors[key];
[100, 200, 300, 400, 500, 600, 700, 800, 900].forEach(colorValue => {
colorSaveList.push(`text-${key}-${colorValue}`);
colorSaveList.push(`bg-${key}-${colorValue}`);
});
}
module.exports = {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}"
],
safelist: colorSaveList,
theme: {
extend: {
colors: extendeColors
}
},
plugins: [
require('tailwind-scrollbar'),
]
}
我目前正在使用 TailwindCss 为我的下一个项目构建组件库,我只是 运行 在处理 Button 组件时遇到了一个小问题。
我正在传递 'primary'
或 'secondary'
之类的道具,它与我在 tailwind.config.js
中指定的颜色相匹配,然后我想将其分配给按钮组件使用Template literals
像这样:bg-${color}-500
<button
className={`
w-40 rounded-lg p-3 m-2 font-bold transition-all duration-100 border-2 active:scale-[0.98]
bg-${color}-500 `}
onClick={onClick}
type="button"
tabIndex={0}
>
{children}
</button>
class 名称在浏览器中显示正常,它在 DOM 中显示 bg-primary-500
,但在应用的样式选项卡中不显示。
主题配置如下:
theme: {
extend: {
colors: {
primary: {
500: '#B76B3F',
},
secondary: {
500: '#344055',
},
},
},
},
但它不应用任何样式。如果我只是手动添加 bg-primary-500
它工作正常。
老实说,我只是想知道这是不是因为 JIT 编译器没有选择动态 class 名称,或者我做错了什么(或者这不是使用 tailWind 的方式) .
欢迎任何帮助,提前致谢!
这种编写 Tailwind 的方式 CSS classes is not recommended. Even JIT mode doesn't 支持它,引用 Tailwind CSS 文档:“Tailwind 不包括任何类型的客户端运行时,因此 class 名称需要在构建时静态提取,并且不能依赖于在客户端更改的任何类型的任意动态值"
所以在发现不推荐这种工作方式并且JIT不支持它之后(感谢慷慨的评论者)。我已将方法更改为更基于 'config' 的方法。
基本上,我为不同的道具定义了一个具有基本配置的常量,并将它们应用于组件。维护工作多了一点,但它完成了工作。
这是一个配置示例。 (目前无需打字)并准备进行一些更好的重构,但您会明白的。
const buttonConfig = {
// Colors
primary: {
bgColor: 'bg-primary-500',
color: 'text-white',
outline:
'border-primary-500 text-primary-500 bg-opacity-0 hover:bg-opacity-10',
},
secondary: {
bgColor: 'bg-secondary-500',
color: 'text-white',
outline:
'border-secondary-500 text-secondary-500 bg-opacity-0 hover:bg-opacity-10',
},
// Sizes
small: 'px-3 py-2',
medium: 'px-4 py-2',
large: 'px-5 py-2',
};
然后我就这样应用样式:
<motion.button
whileTap={{ scale: 0.98 }}
className={`
rounded-lg font-bold transition-all duration-100 border-2 focus:outline-none
${buttonConfig[size]}
${outlined && buttonConfig[color].outline}
${buttonConfig[color].bgColor} ${buttonConfig[color].color}`}
onClick={onClick}
type="button"
tabIndex={0}
>
{children}
</motion.button>
对于 tailwind JIT
模式或使用 JIT
的 v3,您必须确保导出对象样式的文件包含在 tailwind.config.js
的内容选项中,例如
content: ["./src/styles/**/*.{html,js}"],
在 v3 中,正如 Blessing 所说,您可以更改内容数组以支持它。
我有这个
const PokemonTypeMap = {
ghost: {
classes: "bg-purple-900 text-white",
text: "fantasma",
},
normal: {
classes: "bg-gray-500 text-white",
text: "normal",
},
dark: {
classes: "bg-black text-white",
text: "siniestro",
},
psychic: {
classes: "bg-[#fc46aa] text-white",
text: "psíquico",
},
};
function PokemonType(props) {
const pokemonType = PokemonTypeMap[props.type];
return (
<span
className={pokemonType.classes + " p-1 px-3 rounded-3xl leading-6 lowercase text-sm font-['Open_Sans'] italic"}
>
{pokemonType.text}
</span>
);
}
export default PokemonType;
类似于你的方法,然后我将数组移动到一个 JSON 文件,它认为工作正常,但是是浏览器缓存......所以按照 Blessing 的回应,你可以添加 .json像这样
content: ["./src/**/*.{js,jsx,ts,tsx,json}"],
终于有了这段代码,我认为它更好。
import PokemonTypeMap from "./pokemonTypeMap.json";
function PokemonType(props) {
const pokemonType = PokemonTypeMap[props.type];
return (
<span className={pokemonType.classes + " p-1 px-3 rounded-3xl leading-6 lowercase text-sm font-['Open_Sans']"}>
{pokemonType.text}
</span>
);
}
export default PokemonType;
正如有人在此线程中所说,TailWindCSS 3 不支持 动态 class 名称(参见 https://tailwindcss.com/docs/content-configuration#dynamic-class-names)。
我使用 “安全列表” 功能从清除中排除了一些 class 名称。在 tailwind.config.js 你可以使用纯 JS 来开发这样的东西:(它有点 hacky,我同意)
const colors = require('./node_modules/tailwindcss/colors');
const colorSaveList = [];
const extendeColors = {};
for (const key in colors) {
extendeColors[key] = colors[key];
[100, 200, 300, 400, 500, 600, 700, 800, 900].forEach(colorValue => {
colorSaveList.push(`text-${key}-${colorValue}`);
colorSaveList.push(`bg-${key}-${colorValue}`);
});
}
module.exports = {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}"
],
safelist: colorSaveList,
theme: {
extend: {
colors: extendeColors
}
},
plugins: [
require('tailwind-scrollbar'),
]
}