網站首頁 編程語言 正文
前言
本期的源碼閱讀任務是:
- 學會 classnames 的用法
- 學會 classnames 的原理
- 測試用例的使用
源碼地址:JedWatson/classnames: A simple javascript utility for conditionally joining classNames together (github.com)
classnames 的用法
Classname 是一個 JavaScript 庫,它允許您有條件地將類名連接在一起。在構建 React 組件或需要根據某些條件動態生成類名時,它可能非常有用。
下面是一個如何使用 classnames
的例子:
import classnames from 'classnames'; const Button = ({ primary, size }) => { const classes = classnames('btn', { 'btn-primary': primary, 'btn-large': size === 'large', 'btn-small': size === 'small', }); return <button className={classes}>Click me</button>; };
在上面的示例中,classnames
函數接受一個類名和一個將類名映射為布爾值的對象。如果給定類名的布爾值為 true,則該類名將包含在類名的最終列表中。如果值為 false,則不包括類名。
還可以將一個字符串作為第二個參數傳遞給類名,在這種情況下,如果值為 true,那么它將被添加到類名的最終列表中。
const classes = classnames('btn', primary && 'btn-primary');
學會 classnames 的原理
classnames 源碼并不復雜,除去一些兼容性判斷,主要功能實現的代碼如下:
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)) { if (arg.length) { var inner = classNames.apply(null, arg); if (inner) { classes.push(inner); } } } else if (argType === "object") { if ( arg.toString !== Object.prototype.toString && !arg.toString.toString().includes("[native code]") ) { classes.push(arg.toString()); continue; } for (var key in arg) { if (hasOwn.call(arg, key) && arg[key]) { classes.push(key); } } } } return classes.join(" "); }
主要工作原理如下:
- 函數聲明了一個名為
class
的空數組,該數組將用于存儲生成的類名。 - 然后,函數進入一個循環,循環遍歷傳遞給函數的參數。對于每個參數,執行以下步驟:
- 檢查參數的類型。如果它是一個字符串或數字,添加到類數組。
- 如果參數是數組,則函數檢查它是否為非空。如果是,則函數以數組元素作為參數遞歸地調用自身,并將結果添加到類數組中。
- 如果參數是一個對象,那么函數將檢查它是否有一個
toString
方法,該方法不是本機Object.Prototype.toString
方法。如果是這樣,調用oString
的結果將添加到類數組中。如果不是,函數將遍歷對象自己的可枚舉屬性,并將屬性名稱添加到類數組中(如果它們的對應值為真)。 - 循環結束后,將類數組合并到一個單獨的字符串中,使用一個空格字符作為分隔符,并返回結果字符串。
測試用例的使用
className
庫使用 Mocha
進行代碼測試:
Mocha
是一個運行在 Node.js 和瀏覽器上的 JavaScript 測試框架。它用于編寫和運行 JavaScript 代碼的測試用例。
使用 Mocha
寫測試用例的簡單示例:
const assert = require("assert"); describe("myFunction", () => { it("should return the expected result", () => { assert.equal(myFunction(1, 2), 3); }); });
- it 函數用于定義單個測試用例。
- 斷言模塊用于驗證函數是否返回預期的結果。
一些測試用例
describe('classNames', function () { // 測試能夠識別具有真值得對象 it('keeps object keys with truthy values', function () { assert.equal(classNames({ a: true, b: false, c: 0, d: null, e: undefined, f: 1 }), 'a f'); }); // 檢查 classNames 函數是否正確地處理了其輸入參數中的假值,并且只在生成的類名字符串中包含真值。 it('joins arrays of class names and ignore falsy values', function () { assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b'); }); // 這個測試用例檢查 classNames 函數是否正確地處理了各種不同類型的參數 it('supports heterogenous arguments', function () { assert.equal(classNames({a: true}, 'b', 0), 'a b'); }); // 這個測試用例檢查 classNames 函數是否正確地從生成的類名字符串中刪除了前導空格和尾隨空格。 it('should be trimmed', function () { assert.equal(classNames('', 'b', {}, ''), 'b'); }); // 這個測試用例檢查 classNames 函數在調用時是否返回一個空字符串,該函數的唯一參數是一個空對象。 it('returns an empty string for an empty configuration', function () { assert.equal(classNames({}), ''); }); // ... 省略部分測試用例 });
總結
Classname 非常有用,它能夠根據應用程序的狀態構建動態類名。避免編寫冗長和重復的 if-else 語句來構建類名。同時,源碼測試用例寫得非常詳盡,很有借鑒意義,可以用來參考給自己的代碼寫一些測試用例。
原文鏈接:https://juejin.cn/post/7178760381324591163
相關推薦
- 2022-09-06 Redis數據結構SortedSet的底層原理解析_Redis
- 2023-06-18 Python實現兩種稀疏矩陣的最小二乘法_python
- 2022-06-21 C語言超全面講解函數的使用方法上_C 語言
- 2022-04-16 pycharm如何為函數插入文檔注釋_python
- 2021-11-22 Linux下Select多路復用實現簡易聊天室示例_C 語言
- 2022-05-14 一起來學習React元素的創建和渲染_React
- 2022-06-17 Android性能優化之圖片大小,尺寸壓縮綜合解決方案_Android
- 2021-12-09 帶你一文了解C#中的LINQ_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支