在写react的时候动态写入class比较繁琐很啰嗦,记得有个模块能够来解决这个问题,因而乎找到了这个模块叫“classnames”,再者好奇这个模块的体积大小,而后对其进行了源码分析。node
classnames - githubreact
若是不用第三方模块去实现动态添加class是这样子的git
const _classNames = window.people ? 'active main' : 'main';
return (
<div className={_classNames}></div>
)
复制代码
这算比较简单的了,若是条件够多的时候是很可怕的, 想一想就行了!!github
npm安装npm
npm install classnames -S
复制代码
看!相比前面简单明了,结构再复杂同样能应付数组
const sidebarOpenClass = classNames({
main: true,
active: window.people
});
return (
<div className=${_classNames}></div>
)
复制代码
好吧。浏览器
代码并很少,删掉空白行和注释只有仅仅37行的代码,我将在代码里以注释的形式讲解代码含义。bash
(function () {
'use strict';
// => Object.hasOwnProperty 用于判断某个成员是否在对象内
var hasOwn = {}.hasOwnProperty;
function classNames () {
// 存储 className 值
var classes = [];
// 循环实参, arguments就是实际调用函数传入的参数,相似数组
for (var i = 0; i < arguments.length; i++) {
// 获取实参value
var arg = arguments[i];
// 跳过false条件 => false, null, undefined, NaN, 空, ...
if (!arg) continue;
// 判断传入参数的类型
var argType = typeof arg;
// 若是参数的类型是 string 或者 number
if (argType === 'string' || argType === 'number') {
// 直接追加到classes数组后面
classes.push(arg);
// 若是参数是数组而且长度大于0
} else if (Array.isArray(arg) && arg.length) {
// 调用自身函数,利用apply能够将数组转成字符串
var inner = classNames.apply(null, arg);
// 如今是一个字符串,隐士判断布尔值
if (inner) {
// 追加到数组后面
classes.push(inner);
}
// 若是传入的参数是对象
} else if (argType === 'object') {
// 对object进行遍历
for (var key in arg) {
// 判断key是否存在arg对象内而且key的值隐士转换为true
if (hasOwn.call(arg, key) && arg[key]) {
// 将值追加到classes数组后面
classes.push(key);
}
}
}
}
// 将数组链接成字符串以空格拼接 => a b c
return classes.join(' ');
}
// 若是是node.js环境运行
if (typeof module !== 'undefined' && module.exports) {
classNames.default = classNames;
module.exports = classNames;
// 若是用的requirejs模块管理 AMD
} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
define('classnames', [], function () {
return classNames;
});
// 不然运行于浏览器环境
} else {
window.classNames = classNames;
}
}());
复制代码
代码比较少,因此比较好分析。app
classnames使用太灵活了,演示几个demoide
demox1
import classNames from 'classnames';
const _className = classNames('foo'); // => 'foo'
复制代码
demox2
const _className = classNames('foo', {
bar: true
});
// => 'foo bar'
复制代码
demox3
const _className = classNames('foo', {
bar: true,
active: false,
}, ['arr-1', 'arr-2']);
// => foo bar arr-1 arr-2
复制代码
classNames对实参是没有限制的,看源码就明白了,比较经常使用的就是react项目当中。
既然有了第三方插件的存在,就不必重复造轮子了,练习和学习源码是提升技术的好机会,classnames编写了单元测试,覆盖率基本是100%,因此放心使用。