Skip to content

Tailwind 插件机制(addUtilities / addComponents) 属于 👉 “从会用 Tailwind → 能做组件库 / 规范体系” 的分水岭

一、插件机制是干嘛的?

一句话:

用 JS 批量生成 Tailwind 类,而不是手写 CSS

你可以:

  • 定义一组 工具类(utilities)
  • 定义一组 组件类(components)
  • theme() 里的设计变量
  • 自动支持 hover / dark / responsive

二、插件基本结构

js
// tailwind.config.js
import plugin from 'tailwindcss/plugin'

export default {
  theme: { extend: {} },
  plugins: [
    plugin(function ({ addUtilities, addComponents, theme }) {
      // 写插件逻辑
    })
  ]
}

三、addUtilities(工具类)

什么时候用?

👉 单一功能、可自由组合的原子能力

如:

  • .safe-top
  • .text-shadow
  • .scrollbar-hide

1️⃣ 最简单例子

js
addUtilities({
  '.safe-top': {
    paddingTop: 'env(safe-area-inset-top)'
  }
})
html
<div class="safe-top"></div>

2️⃣ 支持响应式 / hover / dark

js
addUtilities(
  {
    '.text-shadow': {
      textShadow: '0 2px 4px rgba(0,0,0,.2)'
    }
  },
  ['responsive', 'hover', 'dark']
)
html
<div class="hover:text-shadow dark:text-shadow"></div>

3️⃣ 从 theme 中取值(核心)

js
addUtilities(
  {
    '.bg-primary-gradient': {
      background: `linear-gradient(
        90deg,
        ${theme('colors.primary.500')},
        ${theme('colors.primary.700')}
      )`
    }
  }
)

📌 这一步 = 插件 + 设计系统打通

4️⃣ 批量生成 utilities(常用技巧)

js
const sizes = {
  sm: '4px',
  md: '8px',
  lg: '16px'
}

addUtilities(
  Object.entries(sizes).map(([key, value]) => ({
    [`.blur-${key}`]: { filter: `blur(${value})` }
  }))
)

使用:

html
<div class="blur-md"></div>

四、addComponents(组件类)

什么时候用?

👉 一整套固定结构样式

如:

  • Button
  • Card
  • Alert
  • Tag

1️⃣ Button 组件例子(核心)

js
addComponents({
  '.btn': {
    padding: '8px 16px',
    borderRadius: theme('borderRadius.md'),
    fontWeight: '500'
  },
  '.btn-primary': {
    backgroundColor: theme('colors.primary.500'),
    color: '#fff',
    '&:hover': {
      backgroundColor: theme('colors.primary.700')
    }
  }
})
html
<button class="btn btn-primary"></button>

📌 btn = 结构 📌 btn-primary = 皮肤

2️⃣ 响应式组件

js
addComponents({
  '.card': {
    padding: '16px',
    '@screen md': {
      padding: '24px'
    }
  }
})

3️⃣ Dark Mode 组件

js
addComponents({
  '.card': {
    backgroundColor: '#fff',
    '.dark &': {
      backgroundColor: '#111'
    }
  }
})

五、addUtilities vs addComponents(重点对比)

维度addUtilitiesaddComponents
定位原子能力组件封装
组合性
是否有语义几乎无
适合场景功能类组件库

📌 经验法则

能拆 → utilities 不想拆 → components

六、addBase(顺带讲)

用来改默认标签样式

js
addBase({
  'h1': { fontSize: theme('fontSize.xl') },
  'h2': { fontSize: theme('fontSize.lg') }
})

📌 常用于:

  • reset
  • markdown 样式

七、实战:做一个「企业级按钮插件」

js
// plugins/button.js
import plugin from 'tailwindcss/plugin'

export default plugin(({ addComponents, theme }) => {
  addComponents({
    '.btn': {
      display: 'inline-flex',
      alignItems: 'center',
      justifyContent: 'center',
      borderRadius: theme('borderRadius.md'),
      padding: '8px 16px',
      fontWeight: '500'
    },
    '.btn-primary': {
      backgroundColor: theme('colors.primary.500'),
      color: '#fff',
      '&:hover': {
        backgroundColor: theme('colors.primary.700')
      }
    },
    '.btn-danger': {
      backgroundColor: theme('colors.danger.500'),
      color: '#fff'
    }
  })
})
js
// tailwind.config.js
import button from './plugins/button'

plugins: [button]

八、和 Vue 组件结合的最佳实践

Tailwind 插件负责「样式规则」

Vue 组件负责「结构 + 逻辑」

vue
<button class="btn" :class="`btn-${type}`">
  <slot />
</button>

九、常见坑(你一定会遇到)

1️⃣ 插件生成的类也会被 purge?

不会(插件是构建时注入)

2️⃣ 插件 vs @apply 怎么选?

  • 公共体系 → 插件
  • 局部组件 → @apply