在我们的项目中运用了一个专门处理类名的库:classnames.它可以根据使用时提供的不同条件自动拼接类名的工具。

使用方法

import classnames from 'classnames';

const divCls = classnames('required', {
    'show-when-disabled-is-false': !disbled,
});

console.log(divCls);

// 当 disbled = true 时:'required '
// 当 disbled = false 时:'required show-when-disabled-is-false'

今天突然来了兴趣,想要看看它的代码是怎么写的。其实看一看它的使用方法也能大概猜出来它的实现原理是对传入的每一个参数进行解析,根据参数类型等条件的不同而采取不同的方式拼接。

源码

这里放一下源码里面重点的部分:

function classNames() {
    var classes = [];

    for (var i = 0; i < arguments.length; i++) {
        var arg = arguments[i];
        if (!arg) continue;

        var argType = typeof arg;

        if (argType === 'string' || argType === 'number') {
            classes.push(arg);
        } 
        // 先将数组排除,因为 typeof [] = 'object'
        // 使用 Array.isArray 可以区分数组和对象
        else if (Array.isArray(arg)) {
            if (arg.length) {
                var inner = classNames.apply(null, arg);
                if (inner) {
                    classes.push(inner);
                }
            }
        } 
        else if (argType === 'object') {
            // 排除构造对象,比如:new Boolean(true)
            // 参考链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof
            if (arg.toString !== Object.prototype.toString) {
                classes.push(arg.toString());
            } else {
                // 能走到这里的数据才是真正的对象
                for (var key in arg) {
                    if (hasOwn.call(arg, key) && arg[key]) {
                        classes.push(key);
                    }
                }
            }
        }
    }

    return classes.join(' ');
}