浅析React动态class类样式绑定方案:classnames库的使用以及如何不使用classnames库的方案
一、classnames库的使用
React 原生动态添加多个className会报错:
import style from './style.css'
<div className={style.class1 style.class2}</div>
想要得到最终渲染的效果是:
<div class='class1 class2'></div>
引入classnames库:
// 1、安装:
npm install classnames --save
// 2、使用:
import classnames from 'classnames'
<div className=classnames({
'class1': true,
'class2': true
)>
</div>
可以将后面的true省略,但这种我认为是比较直观的,可以对传入的class进行比较明显的动态判断
// 其他用法
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
// lots of arguments of various types
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
// 也可以传入数组对象:
var arr = ['b', { c: true, d: false }];
classNames('a', arr); // => 'a b c'
// 可以传入动态class
let buttonType = 'primary';
classNames({ [`btn-${buttonType}`]: true });
在 React 中可以直接在classname内部传入动态class并进行条件判断
// 不使用classnames时的书写方式:
var Button = React.createClass({
// ...
render () {
var btnClass = 'btn';
if (this.state.isPressed) btnClass += ' btn-pressed';
else if (this.state.isHovered) btnClass += ' btn-over';
return <button className={btnClass}>{this.props.label}</button>;
}
});
// 使用了之后可以简化:
var classNames = require('classnames');
var Button = React.createClass({
// ...
render () {
var btnClass = classNames({
btn: true,
'btn-pressed': this.state.isPressed,
'btn-over': !this.state.isPressed && this.state.isHovered
});
return <button className={btnClass}>{this.props.label}</button>;
}
});
二、不需要 classnames 这个库
项目许多库都不是必要的, 我们一个个移除, 今天先移除 classnames
1、使用 classNames 的情况
import classNames from 'classnames';
export default ()=> {
// className 的值: 'dog cat'
return <div className={classNames('dog', {'cat':true, 'fish':false})} />
}
2、如果不使用classNames,根据条件组合样式
export default ()=> {
// className 的值: 'dog cat'
return <div className={['dog', true && 'cat', false && 'fish'].filter(Boolean).join(' ')} />
}
3、方案1:仅使用字符串。这个方案的缺点是不够直观, 但是它的总长度更短
export default ()=> {
// className 的值: 'dog cat false'
return <div className={`dog ${true && 'cat'} ${false && 'fish'}`} />
}
我们保留最后输出的 false
字符串, 为了减少浏览器查找 flase
样式的时间, 声明一个空的 .false
css样式
// css
.false {}
4、方案2:自己简单封装
function names(obj) {
let className = ''
for(const k in obj) {
className += obj[k] || ''
}
return className;
}
export default ()=> {
// className 的值: 'dog cat'
return <div className={names({dog: 1, cat: 0, fish: 1})} />
}
5、对比:classnames 的写法多样,可读性跟 vue 的 :class 绑定比较类似了。本文主要是给了一个观点:用一个语法能解决的问题不需要引入一个库。
分类:
React学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律