classnames 源码学习笔记与解读


theme: healer-readable

我正在参与掘金会员专属活动-源码共读第一期,点击参与

前言

这里我引用源码文档中的一句话来作为开场白:
A simple JavaScript utility for conditionally joining classNames together.

话不多说,咱们直接开始 classnames 的源码学习。

核心源码解读

直接来看它的源码部分,以下这是 classnames 的核心源码,核心源码不过才四十几行,让我们一步步解读一下都是什么意思吧。

    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;
            if (argType === 'string' || argType === 'number') {
                classes.push(arg);
            } else if (Array.isArray(arg) && arg.length) {
                var inner = classNames.apply(null, arg);
                if (inner) {
                    classes.push(inner);
                }
            } else if (argType === 'object') {
                for (var key in arg) {
                    if (hasOwn.call(arg, key) && arg[key]) {
                        classes.push(key);
                    }
                }
            }
        }
        return classes.join(' ');
    }

这里的 hasOwnProperty 这个方法是用来判断对象的属性是否属于自己本身。

整个源码里做了三个 if 类型判断。首先定义 classes 存储数组,然后遍历 arguments 拿到所有的参数;如果该项的值为 undefined、null 之类的就直接跳过;通过 var argType = typeof arg 获取该项的类型,然后 pushclasses 中就可以了。

这里面对我而言比较难懂的是这段代码:

else if (Array.isArray(arg) && arg.length) {
                var inner = classNames.apply(null, arg);
                if (inner) {
                    classes.push(inner);
                }

查阅资料得知这里利用 递归+apply 达到数组扁平化的效果,说的简单点就是将数组分拆成参数传入 classNames 函数中。

最后 returnjoin 方法将数组变为字符串,用空格隔开。

这里介绍一下参数类型的判断:

  • 如果是 string 或者 number,直接 pushclasses
  • 如果是数组,则通过 classNames.apply(null, arg),将数组分拆成参数传给 classNames 函数进行递归
  • 如果是对象,遍历对象,如果 arg[key] 为真,则 pushclasses 数组

classnames 运用

react 项目中,经常使用到 className。使用如下:

<div className="box1"></div>

.box1{
    color:blue;
}

但是缺点也很明显,如果想动态添加类名,className 就有点吃力了。因此这时候就需要 classnames 了。使用 npm install classnames 安装。

众所周知,classnames 是一个库函数,使用方法有很多种,下面介绍一种比较常用的写法。

import classnames from 'classnames';

<div className={classnames({box1:true , box2: false},'box3')}></div>

// 用 className 方式表示如下

<div className="box1 box3"></div>

总结

总体来说,通过阅读源码学到了 argumentsapply 的应用,了解了这个经常使用的库的源码可以更好地理解 classnames 的作用。

从文档中熟悉了 classnames 的用法,从 github 上了解了 classnames 的源码,这是一个与 react 项目紧密结合的库函数,所以多看文档多看源码多学习。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容