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

React15 - sass 中 @mixin 和 @extend 的区别是什么?

在 Sass 中,@mixin@extend 是两个非常重要的代码复用机制,但它们的工作方式和适用场景有显著的区别。理解这些区别对于写出高效、可维护的 Sass 代码至关重要。

核心区别对比

维度 @mixin (混合宏) @extend (继承)
编译方式 复制代码:每次调用都会复制一份样式代码 合并选择器:将选择器合并到同一个规则集中
参数支持 支持:可以传递参数,动态生成样式 不支持:不能传递参数,只能静态继承
代码体积 可能导致代码重复,增加文件体积 代码更精简,减少重复代码
使用场景 需要根据参数动态变化的样式 具有完全相同样式规则的复用
媒体查询 可以在媒体查询内部定义和使用 有限制:不能在媒体查询内部继承外部样式

详细解析与示例

1. @mixin:参数化的代码复制器

@mixin 就像是一个可以接收参数的函数,每次调用时,它会把定义的样式代码复制到当前选择器中。

编译过程示意:

// 定义 mixin
@mixin flex-center($direction: row) {display: flex;flex-direction: $direction;justify-content: center;align-items: center;
}// 使用 mixin
.header {@include flex-center;
}.sidebar {@include flex-center(column);
}.footer {@include flex-center;
}

编译后的 CSS:

.header {display: flex;flex-direction: row;justify-content: center;align-items: center;
}.sidebar {display: flex;flex-direction: column; /* 参数不同,生成了不同的代码 */justify-content: center;align-items: center;
}.footer {display: flex;flex-direction: row; /* 重复了和 header 相同的代码 */justify-content: center;align-items: center;
}

可以看到,.header.footer 的样式代码是完全相同的,但都被复制了一份。

2. @extend:选择器的合并器

@extend 不会复制代码,而是把当前选择器添加到被继承的规则集后面,形成选择器组。

编译过程示意:

// 定义一个基础样式类
.base-button {padding: 10px 20px;border: none;border-radius: 4px;font-size: 14px;cursor: pointer;
}// 继承基础样式
.primary-button {@extend .base-button;background-color: blue;color: white;
}.secondary-button {@extend .base-button;background-color: gray;color: black;
}.success-button {@extend .base-button;background-color: green;color: white;
}

编译后的 CSS:

.base-button,
.primary-button,
.secondary-button,
.success-button {padding: 10px 20px;border: none;border-radius: 4px;font-size: 14px;cursor: pointer;
}.primary-button {background-color: blue;color: white;
}.secondary-button {background-color: gray;color: black;
}.success-button {background-color: green;color: white;
}

关键优势:基础样式只出现一次,所有继承它的选择器共享同一份样式规则。

实际应用场景

适合使用 @mixin 的场景

  1. 需要参数化的样式
@mixin size($width, $height: $width) {width: $width;height: $height;
}.avatar {@include size(40px);
}.cover {@include size(100%, 200px);
}
  1. 浏览器兼容性前缀
@mixin transform($property) {-webkit-transform: $property;-ms-transform: $property;transform: $property;
}.box {@include transform(rotate(45deg));
}
  1. 媒体查询封装
@mixin mobile {@media (max-width: 768px) {@content; // 允许传入额外的样式内容}
}.card {width: 300px;@include mobile {width: 100%; // 移动端样式}
}

适合使用 @extend 的场景

  1. 纯粹的样式复用,无参数变化
%clearfix {&::after {content: "";display: table;clear: both;}
}.container {@extend %clearfix;width: 100%;
}.grid {@extend %clearfix;display: grid;
}
  1. 语义化的类名继承
.error {color: red;font-weight: bold;border: 1px solid red;&:hover {background-color: #ffeeee;}
}.validation-error {@extend .error; // 继承所有 .error 的样式,包括 hoverfont-size: 12px;
}.server-error {@extend .error;padding: 20px;
}

在 React 15 + CSS Modules 中的实践建议

结合你在 React 15 项目中使用 CSS Modules 的场景,这里有一些具体建议:

1. 优先使用 @mixin 的情况

// Button.module.scss// 参数化的按钮变体
@mixin button-variant($bg-color, $text-color: white) {background-color: $bg-color;color: $text-color;&:hover {background-color: darken($bg-color, 10%);}&:active {background-color: darken($bg-color, 15%);}
}.primary {@include button-variant(#1890ff);
}.success {@include button-variant(#52c41a);
}.danger {@include button-variant(#f5222d);
}// 即使样式看起来相似,但因为未来可能独立修改
// 使用 mixin 更灵活

2. 谨慎使用 @extend 的情况

// 在 CSS Modules 中,@extend 可能会有一些陷阱// ✅ 好的使用:继承占位符
%card-base {border-radius: 4px;padding: 16px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}.product-card {@extend %card-base;background: white;
}.user-card {@extend %card-base;background: #f5f5f5;
}// ❌ 避免:继承另一个模块化类名
// 这可能会导致选择器顺序问题,不建议
.special-card {@extend .product-card; // 不推荐,可能导致意外的样式覆盖border: 2px solid gold;
}

3. 结合 CSS Modules 的最佳实践

// styles/mixins.scss
@mixin responsive-spacing($size) {padding: $size * 1px;@media (max-width: 768px) {padding: $size * 0.5px;}
}// components/Card/Card.module.scss
@import "../../styles/mixins";.card {@include responsive-spacing(16);background: white;// 局部样式...
}.card-title {font-size: 18px;font-weight: bold;
}// 需要复用多个样式时,使用组合而非继承
.card-featured {composes: card; // CSS Modules 的组合特性border: 2px solid gold;
}

性能考量

在大型项目中,选择 @mixin 还是 @extend 会影响到最终 CSS 文件的大小:

  • @mixin:如果同一个 mixin 被多次调用且没有参数变化,会产生重复代码,增加文件体积
  • @extend:通过合并选择器减少代码量,但过度使用可能导致选择器过于臃肿
// 不推荐:大量使用无参数 mixin
@mixin hide-text {overflow: hidden;text-indent: 100%;white-space: nowrap;
}.logo {@include hide-text; // 复制一份
}.icon {@include hide-text; // 又复制一份
}// 推荐:使用 extend
%hide-text {overflow: hidden;text-indent: 100%;white-space: nowrap;
}.logo {@extend %hide-text; // 合并选择器
}.icon {@extend %hide-text; // 合并选择器
}

总结

选择依据 推荐使用
需要传参、动态生成 @mixin
纯静态样式复用 @extend
媒体查询内部复用 @mixin
减少代码体积 @extend
样式有独立变化的可能 @mixin
样式永远保持一致 @extend

在实际开发中,我的建议是:

  1. 默认使用 @mixin,它更灵活,意图更明确
  2. 当确定一组样式永远不会改变多处完全一致时,改用 @extend
  3. 在 CSS Modules 中,优先使用 Sass 的 %placeholder 配合 @extend,而不是直接继承类名
  4. 不要过度优化,代码可读性比极致的文件大小更重要
http://www.jsqmd.com/news/519678/

相关文章:

  • 京东再投入350亿助力商家,春晓计划再升级该咋看?
  • 不用Docker!3分钟用Ollama+DeepSeek搭建本地AI助手(Windows版)
  • 深度解析并发编程死锁:原理、场景、排查与解决方案
  • 随机选择算法
  • AI投毒被热议,为什么说百度一下的含金量反而越来越高?
  • React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好?
  • 力扣打卡——搜索二维矩阵、相交链表
  • 深入解析NestedScrollableHost在ViewPager2嵌套滑动场景中的应用
  • 守嘉生殖健康咨询培训,线上学习优势盘点,远超线下培训 - 品牌排行榜单
  • 用Python实战Louvain算法:5步搞定社交网络社区发现(附代码)
  • 永磁同步电机三矢量MPC模型预测电流控制 参考文献:《永磁同步电机三矢量模型预测电流控制_徐艳...
  • python基于HIVE旅游评论数据的旅游形象预测系统 爬虫可视化
  • 研发流程设计(上):如何设计 Go 项目的开发流程?
  • 救命神器!8个一键生成论文工具测评:多场景适配,开题报告+毕业论文+科研写作全搞定
  • DQL(数据查询)
  • 基于Gin的高并发RESTful API设计与Prometheus监控集成:云原生应用性能观测系统实现
  • 电商实战:如何用图神经网络提升商品推荐效果(附代码示例)
  • Gemini 3.1 Pro如何从零生成品牌视觉体系,设计师直呼“被抢活”
  • 知网AI率反复降不下来?比话Pallas引擎专治疑难AI率
  • 科研党必备:Python脚本批量下载Sci-Hub文献(附自动更新域名技巧)
  • 阻塞队列 BlockingQueue
  • 特征图融合三剑客:拼接、相加与相乘的实战指南
  • Day13 | Dart 类核心特性:静态成员、对象操作符与继承机制
  • 比话降AI超15%退款是真的吗?退款流程和条件全解析
  • 相场法在水力压裂模拟中越来越火,尤其是COMSOL这种多物理场耦合神器。今天咱们拆解几个典型工况,手把手看裂缝怎么在代码里“长“出来。先拿最简单的单裂缝开刀——
  • [2015] [Gorila DQN] [Massively Parallel Methods for Deep Reinforcement Learning]
  • Java并发避坑:一文搞懂死锁的本质、实例与解决方案
  • Python数据结构完全指南:列表、字典、元组与集合精通
  • Java锁升级深度解析:从偏向锁到重量级锁,一文读懂锁的“进化”之路
  • 为什么比话敢承诺“不达标全额退款“?技术底气在哪里