本文参加了由公众号@若川视野发起的每周源码共读活动,点击了解详情一起参与。
关于classnames
classnames库的介绍和用法可以参考GitHub地址 github.com/JedWatson/c…
下面是官网用法,将所有类名以空格分开连接在一起,并且对key值为false的不加入进去
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'
如何实现
(function () {
'use strict';
var hasOwn = {}.hasOwnProperty;
function classNames() {
// 定义一个数组用来存放结果
var classes = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!arg) continue;
var argType = typeof arg;
// 字符串或数字直接push
if (argType === 'string' || argType === 'number') {
classes.push(arg);
// 是数组递归调用每一项 这里用到apply传递参数
} else if (Array.isArray(arg)) {
if (arg.length) {
var inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
}
} else if (argType === 'object') {
// 是纯对象的情况下
if (arg.toString === Object.prototype.toString) {
for (var key in arg) {
// 是自己的属性并且值为真就push
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
// 否则就用自己的toString方法
} else {
classes.push(arg.toString())
}
}
}
// 返回用空格隔开的结果
return classes.join(' ');
}
// 支持各种导出形式
if (typeof module !== 'undefined' && module.exports) {
classNames.default = classNames;
module.exports = classNames;
} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
// register as 'classnames', consistent with npm package name
define('classnames', [], function () {
return classNames;
});
} else {
window.classNames = classNames;
}
}());
总结
- 学到了使用递归+apply将数组达到扁平化传递参数
- 如何支持各种导出模式