如何利用Less实现交互状态样式的统一 通过Mixin封装行为最佳实践|Duuu笔记
Mixin封装交互状态需接收选择器参数,如.interactive-states('.btn'),禁用&:hover写法;disabled需同时匹配[disabled]和[aria-disabled="true"];避免循环调用以防CSS体积膨胀。
Less里怎么用Mixin封装:hover/:focus这类交互状态
直接把伪类写进Mixin里是最常用也最稳妥的做法,不是所有状态都适合抽离,但:hover、:active、:focus、:disabled这四个高频组合完全可以。
关键在于Mixin要接收选择器上下文,否则编译后样式会丢失层级关系。别用
.button:hover
这种硬编码,得让调用方决定作用对象。
写法必须带参数:
.interactive-states(@selector) { @selector:hover { ... } }
调用时传入选择器片段,比如
.interactive-states('.btn');
,而不是
.interactive-states(btn);
(后者会被当成变量)
如果需要支持多状态叠加(如
:hover:focus
),得单独再写一个Mixin,不要强行塞进同一个里——语义混乱,维护成本高
为什么不能直接在Mixin里写&:hover
因为
&
在Mixin内部指向的是Mixin自身定义的作用域,不是调用它的地方。你写
&:hover
,编译出来就是
.mixin-name:hover
,完全没用。
真正有效的写法是把
&
留在调用侧,让Mixin只负责声明块内容:
“
(深入)
”;
.interactive-states() {
&:hover { color: #007bff; }
&:active { transform: translateY(1px); }
}
.btn {
.interactive-states();
}
这样编译结果才是
.btn:hover
和
.btn:active
。漏掉这层理解,90%的封装都会失效。
disabled状态怎么兼容原生表单控件和自定义组件
原生
和
走的是HTML属性逻辑,而自定义组件(比如
.custom-btn[aria-disabled="true"]
)得靠属性选择器。Mixin得同时覆盖两种写法,否则样式不生效。
统一用
[disabled]
匹配原生控件
加一层
[aria-disabled="true"]
适配React/Vue组件库
避免只写
:disabled
——它对
div
或自定义标签无效
示例:
&[disabled], &[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
性能和编译体积容易被忽略的点
每次调用Mixin都会复制一遍CSS规则,如果在循环中用(比如遍历按钮类型),生成的CSS可能翻倍。不是语法错误,但上线后查Network会发现样式表比预期大一截。
优先用CSS类名控制状态(
.is-disabled
),而不是纯伪类+Mixin
如果必须用伪类,确保Mixin只在顶层组件类下调用一次,别在嵌套选择器里反复调用
Less 4.0+支持
extend
,但
:hover
类不能被
extend
,这点文档没明说,实测会静默失败
状态封装真正的难点不在写法,而在厘清「谁触发状态」「谁响应状态」「状态是否可预测」——CSS本身没状态管理能力,全靠约定和约束撑住。
