在寫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%,因此放心使用。