当前位置: 首页 > news >正文

基类+修饰类

“基类 + 修饰类”是 CSS 工程化中最经典、最优雅的命名与组织模式。它源自BEM(Block Element Modifier)方法论,但在 Vue 3 组件化开发中被发挥到了极致。

你可以把这种模式理解为“乐高积木设计法”

  • 基类(Base):定义一块积木的“通用骨架”(尺寸、字体、基础颜色)。
  • 修饰类(Modifier):定义这块积木的“特定皮肤”“特殊状态”(颜色变红、尺寸变大、是否禁用)。

这样做最大的好处是:永远不需要写重复的样式代码,一个类只干一件事。


一、命名规范(BEM 标准写法)

在 CSS 中,我们通常用---来区分:

类型命名格式示例含义
基类(Block).block.btn按钮的基础样式(宽高、内边距、边框圆角)
修饰类(Modifier).block--modifier.btn--primary
.btn--large
主题色变为主色
尺寸变大
状态类(State).is-状态.block.is-状态.is-disabled
.is-active
临时状态(禁用、激活中),通常配合 JS 控制

二、原生 CSS 中的写法(如何组合)

假设我们要做一个按钮组件:

<!-- 1. 只写基类:默认灰色普通按钮 --> <button class="btn">默认按钮</button> <!-- 2. 基类 + 修饰类:变成蓝色大按钮 --> <button class="btn btn--primary btn--large">主要大按钮</button> <!-- 3. 基类 + 状态类:变成禁用状态 --> <button class="btn is-disabled" disabled>禁用按钮</button>

对应的 CSS 代码(利用层叠覆盖):

/* 基类:定义所有按钮共有的骨架 */ .btn { display: inline-block; padding: 8px 16px; font-size: 14px; border-radius: 4px; border: 1px solid #dcdfe6; background: #fff; color: #606266; cursor: pointer; transition: all 0.3s; } /* 修饰类:只改颜色(基类里有的属性,覆盖掉即可) */ .btn--primary { background: #409eff; border-color: #409eff; color: #fff; } /* 修饰类:只改尺寸 */ .btn--large { padding: 12px 24px; font-size: 16px; } /* 状态类:只改交互反馈 */ .is-disabled { opacity: 0.6; cursor: not-allowed; pointer-events: none; /* 禁止点击事件 */ }

三、🔥 Vue 3 中的最佳实践(动态绑定修饰类)

在 Vue 中,你极少会在模板里硬编码写死class="btn btn--primary"(因为这样就失去响应式意义了)。正确做法是利用:class动态绑定,将修饰类与组件的props或响应式状态关联起来。

1. 封装一个通用的BaseButton.vue组件

这是你在 Vite 项目中实际会写的代码:

<!-- src/components/BaseButton.vue --> <template> <button class="btn" :class="[ `btn--${type}`, // 动态主题(primary / success / warning) { 'is-disabled': disabled, [`btn--${size}`]: size // 动态尺寸(large / small) } ]" :disabled="disabled" > <slot /> </button> </template> <script setup lang="ts"> // 定义组件的 API,让父组件通过传参来控制样式 type ButtonType = 'default' | 'primary' | 'success' | 'warning'; type ButtonSize = 'default' | 'large' | 'small'; const props = withDefaults(defineProps<{ type?: ButtonType; size?: ButtonSize; disabled?: boolean; }>(), { type: 'default', size: 'default', disabled: false, }); </script> <style scoped> /* 基类 */ .btn { padding: 8px 16px; font-size: 14px; border-radius: 4px; border: 1px solid transparent; cursor: pointer; transition: all 0.3s; /* 默认样式(default) */ background: #fff; border-color: #dcdfe6; color: #606266; } .btn:hover:not(.is-disabled) { opacity: 0.8; } /* 修饰类:主题 */ .btn--primary { background: #409eff; border-color: #409eff; color: #fff; } .btn--success { background: #67c23a; border-color: #67c23a; color: #fff; } .btn--warning { background: #e6a23c; border-color: #e6a23c; color: #fff; } /* 修饰类:尺寸 */ .btn--large { padding: 12px 24px; font-size: 16px; } .btn--small { padding: 6px 12px; font-size: 12px; } /* 状态类 */ .is-disabled { opacity: 0.6; cursor: not-allowed; } </style>
2. 父组件中使用(干净得像写 HTML 属性):
<template> <!-- 默认灰色 --> <BaseButton>提交</BaseButton> <!-- 主要蓝色,大号 --> <BaseButton type="primary" size="large">提交</BaseButton> <!-- 警告色,禁用 --> <BaseButton type="warning" disabled>已过期</BaseButton> </template>

四、配合 CSS 预处理器(SCSS)的进阶写法

如果你在 Vite 中安装了sasspnpm add -D sass),可以用 SCSS 的&父选择器语法,让修饰类嵌套在基类内部,逻辑更集中:

.btn { padding: 8px 16px; // ... // 使用 & 代表 .btn,生成 .btn--primary &--primary { background: #409eff; color: #fff; } &--large { padding: 12px 24px; } // 状态类也嵌套进去,生成 .btn.is-disabled &.is-disabled { opacity: 0.6; cursor: not-allowed; } }

五、基类 + 修饰类 vs 原子化 CSS(Tailwind)

既然你是 Vite 项目,可能会听到“Tailwind CSS(原子类)”。这两种模式不冲突,而是互补:

模式基类 + 修饰类(BEM)原子化 CSS(Tailwind)
写法.btn--primary { background: blue; }class="bg-blue-500"
优点逻辑清晰,语义强,适合组件库内部开发极快,不用想类名,适合业务页面
缺点需要频繁在 HTML 和 CSS 间切换类名太长,可读性依赖工具提示

大厂最佳实践(Vue 3 生态)

  • 组件内部(如 Element Plus / Naive UI):用基类+修饰类,提供语义化的type/sizeProps。
  • 业务页面(App.vue 或具体页面):用原子类(配合unocsstailwind)快速搭建布局。

给你一个无敌的“避坑原则”

  1. 永远不要在基类里写死.btn { color: red; },把颜色留给修饰类。
  2. 状态类(.is-*)不要单独使用,必须配合基类一起出现(class="btn is-disabled"),因为 CSS 权重靠组合提升。
  3. 修饰类只覆盖基类中已有的属性,如果基类没写border-radius,修饰类里也不要写,除非你想新增特性。

现在你可以在你的 Vite 项目里试着封装一个BaseButton了,把之前学的transition:hoverbox-sizing都结合进去。封装完这个组件,你对 CSS 模块化的理解直接上一个台阶。

接下来想学transition过渡动画(让按钮渐变消失/出现),还是想攻克position定位(做吸顶导航、浮动客服按钮)?你来挑。

http://www.jsqmd.com/news/1249282/

相关文章:

  • SpringBoot--一个注解实现Redisson分布式锁
  • 苏州黄金回收需要实名登记吗?流程严不严 - 生活时报
  • 真力时售后服务中心全部地址及热线电话实地考察报告_多信源验证(2026年7月最新) - 亨得利官方服务中心
  • proxmox openwrt软路由 群晖折腾总结
  • 2026北京“柜姐内购价”包与专柜正价款回收价差:员工折扣入手的包,二手回收怎么算? - 日常财经早知道
  • AI自动生成会议纪要:3个被90%团队忽略的提示词陷阱,今天不改明天误事
  • 关于在VM虚拟机下,安装OpenWrt软路由,所遇错误及解决方法。
  • BERT模型在文本分类任务中的实践与优化
  • 2026江岸靠谱装修公司大盘点:从透明报价到施工质量全面对比 - 资讯纵览
  • 华中科技大学计算机组成原理实验—CPU设计实验报告
  • 2026东莞PLC培训机构客观实力排名(公开数据整理择校参考)+FAQ问答 - 互联网科技品牌测评
  • 一文吃透 OpenSSH:远程 CLI 连接、密钥免密登录、服务安全配置教程
  • 深入解析MSPM0 LCD驱动:从电压生成到多路复用的嵌入式显示技术
  • 同芯同行 信创未来—— 麒麟信安受邀参加2021信息技术应用创新高峰论坛
  • 从麦哲伦到郑和,一堂课飘洋过海 - 东方既白~(-^
  • 腾讯多模态智能鉴伪系统解析与金融应用实践
  • 2026年实测免费去水印小程序怎么选 - 免费软件工具方法教程
  • 2026重庆实木楼梯踏步楼梯栏杆定制选购指南 - LYL仔仔
  • 2026年贵阳废品回收服务盘点:金属回收与厂房拆除需求全满足 - 兔兔不是荼荼
  • 2026 翡翠行业头部玩家盘点:瑞丽市论邦珠宝店为何难以撼动榜首地位? - 互联网科技品牌测评
  • GB/T 4857.23随机振动介绍,GB/T 4857.23-2021标准及附录D谱图说明
  • 南京江诗丹顿售后服务中心|售后电话及地址权威公告(2026年7月最新) - 江诗丹顿中国服务中心
  • 软路由虚拟服务器,VMware虚拟机安装软路由(OpenWrt)详细教程
  • 数字孪生与AI技术在高安全营区智能治理中的应用
  • 当墓园开始“讲故事”,墓碑就不再只是石头
  • Qwen3.5-9B轻量化部署:GGUF量化与Ollama本地实践
  • 解决:fatal: unable to access... OpenSSL SSL_read: Connection was reset, errno 10054
  • 石家庄黄金回收禹竞|2026闲置旧金、18K金高价回收,本地正规回收门店盘点避坑指南 - 企业家观察员
  • BOOST
  • 谷歌广告投放公司推荐:外贸企业代运营收费标准与服务商选择方法 - 麦麦唛