源码第一句介绍
A simple JavaScript utility for conditionally joining classNames together.
一个简单的、有条件的绑定多个className的JavaScript实用函数
用法
classnames函数支持多个传参,支持数值、字符串、对象、数组等
classnames(class1, class2, ...classN)
基本用法
// 多个字符串 两种写法均可
classNames('mt10', 'font20') // => 'mt10 font20'
classNames('mt10 font20') // => 'mt10 font20'
//「字符串+对象」组合
classNames('switch', { selected: false }) // => 'switch'
classNames('switch', { selected: true }) // => 'switch selected'
// 对象 三种写法均可
classNames({ switch: true }, { selected: true }); // => 'switch selected'
classNames({ switch: true, selected: true }); // => 'switch selected'
classNames({ 'switch selected': true }); // => 'switch selected'
// 数组
classNames('font20', ['mt10', { switch: true, selected: false }]); // => 'font20 mt10 switch'
ES6语法
支持变量
const disabled = 'disabled';
classNames('radio', { [`radio-${disabled}`]: true }); // => 'radio radio-disabled'
classNames('radio', `radio-${disabled}`); // => 'radio radio-disabled'
结合React和CSSmodule
在React中,class写为className
import classNames from 'classnames';
import Style from './index.less'
const isHorizontal = true
const checkboxCls = classNames(
'global-style',
Style.checkboxGroup,
{ [Style.checkboxGrouphHorizontal]: isHorizontal },
);
<div className={checkboxCls}></div>
小结
classnames支持多种写法
classnames函数的入参是无序的,但是编写习惯是字符串类型的放前面,其他放后面
classnames函数会忽略入参中的错误值
classnames函数支持动态类名
原理
核心目标:
对不同类型入参进行不同处理,统一转换为为字符串,最终返回一个拼接的字符串
实现自己的classnames
function classNames (...args) {
let classes = ''
// 遍历解析每个入参,拼接到类字符串中
args.forEach(arg => {
if(arg) classes = appendClass(classes, parseValue(arg))
})
return classes
}
// 解析某个值为字符串
function parseValue(value) {
// 如果是字符类型直接返回该字符串
if (typeof value === 'string') return value
// 如果不是对象类型返回空字符
if (typeof value !== 'object') return ''
// 如果是数组,apply扁平化数组递归classNames返回类名字符串
if (Array.isArray(value)) {
return classNames.apply(null, value)
}
// 如果对象自定义了toString方法
if(value.toString !== Object.prototype.toString) return value.toString()
let classes = ''
// 一般对象 拼接自定义属性且值为true的key到类名字符串
Object.keys(value).forEach(key => {
if (value[key]) classes = appendClass(classes, key)
})
return classes
}
// 拼接字符串
function appendClass(value, newValue) {
if(!newValue) return value
// 如果是首次则直接返回新字符串,否则返回拼接结果
return value ? `${value} ${newValue}` : newValue
}
拓展
深拷贝实现,也是根据不同数据类型采取不同的拷贝方式。