
传统上,当使用 tailwind css 编写组件变体时,我会使用简单的类映射将 prop 值映射到组件插槽:
type ttheme = "default" | "secondary";
interface icomponentslot {
root: string;
accent: string;
}
const theme_map: record<ttheme, icomponentslot> = {
default: {
root: "bg-red hover:background-pink",
accent: "text-blue hover:text-green",
},
secondary: {
root: "bg-green hover:background-black",
accent: "text-pink hover:text-white",
}
}
<div :class="theme_map['default'].root">
<div :class="theme_map['default'].accent">/**/</div>
</div>
这种方法的问题是保持所需的类相互一致,确保每个变体都具有所有必需的类,特别是在更复杂的组件中。在我们想要跨不同组件插槽共享样式(例如文本颜色)的组件中,需要我们单独更新每个插槽。
tailwind 通过扫描代码库和匹配字符串来生成实用程序类,这意味着虽然 tailwind 可以从任意值创建类,但我们无法在不创建安全列表的情况下动态启动它们。所以这行不通:
// .ts
type ttheme = "default" | "secondary";
const colors: record<ttheme, string> = {
default: "red",
secondary: "blue",
}
// .html
<div :class="`text-[${colors[default]}]`">
但是,我们可以通过利用 css 变量来模仿所需的行为,这是 tailwind 在其许多类的底层使用的东西。我们可以使用以下语法通过 tailwind 中的类设置变量: [--my-variable-key:--my-variable-value]
那么我们如何更新上面的代码示例以使用动态值?
// .ts
type ttheme = "default" | "secondary";
const colors: record<ttheme, string> = {
default: "[--text-color:red]",
secondary: "[--text-color:blue]",
}
// .html
<div
:class="[
colors[default],
'text-[--text-color]'
]">
现在我们了解了 tailwind 的局限性,我们需要研究解决由类映射方法引起的初始问题的方法。我们可以从简化我们的类映射开始:
type ttheme = "default" | "secondary";
interface icomponentslot {
root: string;
accent: string;
}
const theme_map: record<ttheme, string> = {
default: "[--backgound:red] [--hover__background:pink] [--text:blue] [--hover__text:green]",
secondary: "[--backgound:green] [--hover__background:black] [--text:pink] [--hover__text:white]",
}
<div class="bg-[--background] hover:bg-[--hover__background]">
<div class="text-[--text] hover:text-[--hover__text">/**/</div>
</div>
不幸的是,仅此并不能解决我们的问题,我们仍然无法确保我们已经设置了正确显示每个变体所需的所有类。那么我们如何才能更进一步呢?好吧,我们可以开始编写一个接口来强制我们设置指定的值:
interface icomponentthemevariables {
backgound: string;
hover__backgound: string;
text: string;
hover__text: string;
}
const theme_map: record<ttheme, icomponentthemevariables> = {
default: {
backgound: "[--backgound:red]",
text: "[--hover__background:pink]",
hover__background: "[--text:blue]",
hover__text:"[--hover__text:green]",
},
secondary: {
backgound: "[--backgound:green]",
text: "[--hover__background:black]",
hover__background: "[--text:pink]",
hover__text:"[--hover__text:white]",
},
}
所以这可行,但是,仍然有一个问题,没有什么可以阻止我们混合字符串值。例如,我们可能不小心将关键背景设置为 [--text:blue]。
所以也许我们也应该输入我们的值。我们无法输入整个类,这将是维护的噩梦,那么如果我们输入颜色并编写一个辅助方法来生成 css 变量会怎么样:
type tcolor = "red" | "pink" | "blue" | "green" | "black" | "white";
interface icomponentthemevariables {
backgound: tcolor;
hover__backgound: tcolor;
text: tcolor;
hover__text: tcolor;
}
// example variablemap method at the end of the article
const theme_map: record<ttheme, string> = {
default: variablemap({
backgound: "red",
text: "pink",
hover__background: "blue",
hover__text:"green",
}),
secondary: variablemap({
backgound: "green",
text: "black",
hover__background: "pink",
hover__text:"white",
}),
}
好的,这太棒了,我们可以确保始终为组件的每个变体设置正确的变量。但是等等,我们刚刚遇到了 tailwind 发现的最初问题,我们不能只生成类,tailwind 不会选择它们。那么我们该如何解决这个问题呢?
js 中的 css 似乎是显而易见的答案,只需生成一个类,该类创建具有正确变量的自定义类。但有一个障碍,javascript 在客户端上运行,这会导致“flash”,组件最初加载时没有设置变量,然后更新才能正确显示。
立即学习“前端免费学习笔记(深入)”;
十天学会易语言图解教程用图解的方式对易语言的使用方法和操作技巧作了生动、系统的讲解。需要的朋友们可以下载看看吧!全书分十章,分十天讲完。 第一章是介绍易语言的安装,以及运行后的界面。同时介绍一个非常简单的小程序,以帮助用户入门学习。最后介绍编程的输入方法,以及一些初学者会遇到的常见问题。第二章将接触一些具体的问题,如怎样编写一个1+2等于几的程序,并了解变量的概念,变量的有效范围,数据类型等知识。其后,您将跟着本书,编写一个自己的MP3播放器,认识窗口、按钮、编辑框三个常用组件。以认识命令及事件子程序。第
3
像 emotion 这样的库通过插入有关组件的内联样式标签来处理这个问题:
<body>
<div>
<style data-emotion-css="21cs4">.css-21cs4 { font-size: 12 }</style>
<div class="css-21cs4">text</div>
</div>
</body>
这对我来说不是正确的方法。
我正在使用 vue,这让我走上了 css 中 v-bind 的道路,这是 vue 中将 javascript 绑定为 css 值的功能。过去我只很少使用这个功能,并且从未深入研究过它的用途。 css 中的 v-bind 只是在相关元素上设置内联样式。
这让我想起了几个月前我从 tailwind css 的创建者 adam wathan 那里看到的一条推文:
那么这对我们有什么帮助呢?好吧,虽然我们无法动态生成 tailwind 类,但我们可以动态生成内联样式并使用 tailwind 类中的这些内联样式。那会是什么样子?
type tcolor = "red" | "pink" | "blue" | "green" | "black" | "white";
interface icomponentthemevariables {
backgound: tcolor;
hover__backgound: tcolor;
text: tcolor;
hover__text: tcolor;
}
// example variablemap method at the end of the article
const theme_map: record<ttheme, string> = {
default: variablemap({
backgound: "red",
text: "pink",
hover__background: "blue",
hover__text: "green",
}),
secondary: variablemap({
backgound: "green",
text: "black",
hover__background: "pink",
hover__text: "white",
}),
}
<div
class="bg-[--background] hover:bg-[--hover__background]"
:style="theme_map['default']"
>
<div class="text-[--text] hover:text-[--hover__text">/**/</div>
</div>
/*
output:
<div
class="bg-[--background] hover:bg-[--hover__background]"
style="--background: red; --text: pink; --hover__background: blue; --hover__text: green;"
>
<div class="text-[--text] hover:text-[--hover__text">...</div>
</div>
*/
通过结合 typescript、css 变量和内联样式的功能,我们能够确保在使用 tailwind css 时,我们组件的每个变体都会设置每个选项并具有正确的类型。
这是一种实验性方法,我相信会有一些强烈的意见。我确信这是最好的方法吗?现阶段,我不确定,但我认为它有腿。
如果您觉得这篇文章有趣或有用,请在 bluesky(我在这里最活跃)、medium、dev 和/或 twitter 上关注我。
// variableMap example
export const variableMap = <T extends Record<string, string>>(
map: T
): string => {
const styles: string[] = [];
Object.entries(map).forEach(([key, value]) => {
const wrappedValue = value.startsWith("--") ? `var(${value})` : value;
const variableClass = `--${key}: ${wrappedValue};`;
styles.push(variableClass);
});
return styles.join(" ");
};
以上就是使用 Tailwind CSS 编写组件变体的不同方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号