域名 AXUM.RS 将于2025年10月到期。我们无意再对其进行续费,我们希望你能够接续这个域名,让更多 AXUM 开发者继续受益。现在,我们已启用新域名 AXUM.EU.ORG
  • 方案AXUM.RS 域名 = 3000
如果你有意接续这份 AXUM 情怀,请与我们取得联系。
说明:
  1. 如果有人购买 AXUM.RS 域名,或者该域名到期,本站将使用免费域名 AXUM.EU.ORG 继续提供服务。

Tailwind: 复用

本章通过将之前撸的按钮改成 NextJS 版,进而讨论 Tailwind 的复用原则。

先来回顾一下我们之前撸的按钮:

<button class="bg-blue-600 text-gray-50 px-6 py-2 rounded shadow hover:bg-blue-700 hover:-translate-y-1 hover:shadow-md transition-all duration-500">点我</button>

Tailwind 的复用方式

使用 CSS 复用

使用 CSS 复用可能是很多人第一想法,毕竟像上面那个按钮那样,它的 class 属性太长了。我们可以将其抽取成一个 .btn

<button class="btn">点我</button>

相应的,在 CSS 文件里(比如 nextjs 的 styles/globals.css)定义这个 .btn

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .btn {
    @apply bg-blue-600 text-gray-50 px-6 py-2 rounded shadow hover:bg-blue-700 hover:-translate-y-1 hover:shadow-md transition-all duration-500;
  }
}

这些带 @ 前缀的,是 PostCSS 指令(这不是我们的关注点,如果你对 PostCSS 有兴趣,请自行搜索资料进行学习),其中:

本小节代码:axum-rs-nextjs-with-tailwind-btn-css

使用 React/NextJS 的组件进行复用

首先,我们创建一个 Button 组件:

// components/Button.jsx

export default function Button({ children }) {
  return (
    <button className="bg-blue-600 text-gray-50 px-6 py-2 rounded shadow hover:bg-blue-700 hover:-translate-y-1 hover:shadow-md transition-all duration-500">
      {children}
    </button>
  );
}

然后就可以使用它了:

<Button>点我</Button>

本小节代码:axum-rs-nextjs-with-tailwind-btn-1

复用原则

通过 React/NextJS/Vue 的组件进行复用 Tailwind。当需要一些辅助性的样式时,可以通过 CSS 进行定义。

扩展这个按钮组件

目前我们这个按钮组件只有一种蓝色,在实际项目中需要多种颜色,我们可以通过增加 color 来接收需要的颜色:

然后你可能在 Button 组件里这样写:

export default function Button({ children,color }) {
  return (
    <button className={`bg-${color}-600 text-gray-50 px-6 py-2 rounded shadow hover:bg-${color}-700 hover:-translate-y-1 hover:shadow-md transition-all duration-500`}>
      {children}
    </button>
  );
}

这是一个严重的错误!

不要通过变量值来拼接 Tailwind 的类名

PostCSS 是按 tailwind 的类名进行处理的,它并不会处理 bg-${color}-600 这样的 JS 表达式,而是把它当成一个字符串,显然我们并没有定义 .bg-${color}-600 这样的 CSS 类,所以最终结果就是样式丢失。

而是通过JS的条件判断给定完整的 Tailwind 的类名

<Button>蓝色按钮</Button>
<Button type="red">红色按钮</Button>
<Button type="gray">灰色按钮</Button>

然后实现 Button 组件:

export default function Button({ children, type }) {
  let color = 'bg-blue-600';
  let hoverColor = 'hover:bg-blue-700';

  switch (type) {
    case 'red': {
      color = 'bg-red-600';
      hoverColor = 'hover:bg-red-700';
      break;
    }
    case 'gray': {
      color = 'bg-gray-600';
      hoverColor = 'hover:bg-gray-700';
      break;
    }
  }

  const classList = `${color} text-gray-50 px-6 py-2 rounded shadow ${hoverColor} hover:-translate-y-1 hover:shadow-md transition-all duration-500`;

  return <button className={classList}>{children}</button>;
}
  • 针对不同的 type 设置不同的颜色
  • 把具体颜色和其它 CSS 类组成完整的列表
  • 将这个列表传递给 <button> 元素

你或许会有疑问:

  1. 不是说 JSX 里只能用表达式吗,这里怎么跑出来了 switch 语句
    1. 我们说的 JSX 是指具体的 JSX 语句,不是指 *.jsx 文件。
    2. <button className={classList}>{children}</button> 里,只能用 JS 表达式,因为它是 JSX 语句;而在其它地方是 JS 环境,自然可以用包括语句在内的任何 JS 语法
  2. classList不也是在拼接吗
    1. 它拼接的是完整的列表,里面的每一项都是完整的 CSS 类名
    2. 我们说的是不要拼接 CSS 类名
  1. 我们说的 JSX 是指具体的 JSX 语句,不是指 *.jsx 文件。
  2. <button className={classList}>{children}</button> 里,只能用 JS 表达式,因为它是 JSX 语句;而在其它地方是 JS 环境,自然可以用包括语句在内的任何 JS 语法
  1. 它拼接的是完整的列表,里面的每一项都是完整的 CSS 类名
  2. 我们说的是不要拼接 CSS 类名

本小节代码:axum-rs-nextjs-with-tailwind-btn-2

要查看完整内容,请先登录