React?classnames原理及測(cè)試用例
前言
本期的源碼閱讀任務(wù)是:
- 學(xué)會(huì) classnames 的用法
- 學(xué)會(huì) classnames 的原理
- 測(cè)試用例的使用
classnames 的用法
Classname 是一個(gè) JavaScript 庫(kù),它允許您有條件地將類(lèi)名連接在一起。在構(gòu)建 React 組件或需要根據(jù)某些條件動(dòng)態(tài)生成類(lèi)名時(shí),它可能非常有用。
下面是一個(gè)如何使用 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
函數(shù)接受一個(gè)類(lèi)名和一個(gè)將類(lèi)名映射為布爾值的對(duì)象。如果給定類(lèi)名的布爾值為 true,則該類(lèi)名將包含在類(lèi)名的最終列表中。如果值為 false,則不包括類(lèi)名。
還可以將一個(gè)字符串作為第二個(gè)參數(shù)傳遞給類(lèi)名,在這種情況下,如果值為 true,那么它將被添加到類(lèi)名的最終列表中。
const classes = classnames('btn', primary && 'btn-primary');
學(xué)會(huì) classnames 的原理
classnames 源碼并不復(fù)雜,除去一些兼容性判斷,主要功能實(shí)現(xiàn)的代碼如下:
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(" "); }
主要工作原理如下:
- 函數(shù)聲明了一個(gè)名為
class
的空數(shù)組,該數(shù)組將用于存儲(chǔ)生成的類(lèi)名。 - 然后,函數(shù)進(jìn)入一個(gè)循環(huán),循環(huán)遍歷傳遞給函數(shù)的參數(shù)。對(duì)于每個(gè)參數(shù),執(zhí)行以下步驟:
- 檢查參數(shù)的類(lèi)型。如果它是一個(gè)字符串或數(shù)字,添加到類(lèi)數(shù)組。
- 如果參數(shù)是數(shù)組,則函數(shù)檢查它是否為非空。如果是,則函數(shù)以數(shù)組元素作為參數(shù)遞歸地調(diào)用自身,并將結(jié)果添加到類(lèi)數(shù)組中。
- 如果參數(shù)是一個(gè)對(duì)象,那么函數(shù)將檢查它是否有一個(gè)
toString
方法,該方法不是本機(jī)Object.Prototype.toString
方法。如果是這樣,調(diào)用oString
的結(jié)果將添加到類(lèi)數(shù)組中。如果不是,函數(shù)將遍歷對(duì)象自己的可枚舉屬性,并將屬性名稱添加到類(lèi)數(shù)組中(如果它們的對(duì)應(yīng)值為真)。 - 循環(huán)結(jié)束后,將類(lèi)數(shù)組合并到一個(gè)單獨(dú)的字符串中,使用一個(gè)空格字符作為分隔符,并返回結(jié)果字符串。
測(cè)試用例的使用
className
庫(kù)使用 Mocha
進(jìn)行代碼測(cè)試:
Mocha
是一個(gè)運(yùn)行在 Node.js 和瀏覽器上的 JavaScript 測(cè)試框架。它用于編寫(xiě)和運(yùn)行 JavaScript 代碼的測(cè)試用例。
使用 Mocha
寫(xiě)測(cè)試用例的簡(jiǎn)單示例:
const assert = require("assert"); describe("myFunction", () => { it("should return the expected result", () => { assert.equal(myFunction(1, 2), 3); }); });
- it 函數(shù)用于定義單個(gè)測(cè)試用例。
- 斷言模塊用于驗(yàn)證函數(shù)是否返回預(yù)期的結(jié)果。
一些測(cè)試用例
describe('classNames', function () { // 測(cè)試能夠識(shí)別具有真值得對(duì)象 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 函數(shù)是否正確地處理了其輸入?yún)?shù)中的假值,并且只在生成的類(lèi)名字符串中包含真值。 it('joins arrays of class names and ignore falsy values', function () { assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b'); }); // 這個(gè)測(cè)試用例檢查 classNames 函數(shù)是否正確地處理了各種不同類(lèi)型的參數(shù) it('supports heterogenous arguments', function () { assert.equal(classNames({a: true}, 'b', 0), 'a b'); }); // 這個(gè)測(cè)試用例檢查 classNames 函數(shù)是否正確地從生成的類(lèi)名字符串中刪除了前導(dǎo)空格和尾隨空格。 it('should be trimmed', function () { assert.equal(classNames('', 'b', {}, ''), 'b'); }); // 這個(gè)測(cè)試用例檢查 classNames 函數(shù)在調(diào)用時(shí)是否返回一個(gè)空字符串,該函數(shù)的唯一參數(shù)是一個(gè)空對(duì)象。 it('returns an empty string for an empty configuration', function () { assert.equal(classNames({}), ''); }); // ... 省略部分測(cè)試用例 });
總結(jié)
Classname 非常有用,它能夠根據(jù)應(yīng)用程序的狀態(tài)構(gòu)建動(dòng)態(tài)類(lèi)名。避免編寫(xiě)冗長(zhǎng)和重復(fù)的 if-else 語(yǔ)句來(lái)構(gòu)建類(lèi)名。同時(shí),源碼測(cè)試用例寫(xiě)得非常詳盡,很有借鑒意義,可以用來(lái)參考給自己的代碼寫(xiě)一些測(cè)試用例。
以上就是React classnames原理及測(cè)試用例的詳細(xì)內(nèi)容,更多關(guān)于React classnames測(cè)試用例的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react-native組件中NavigatorIOS和ListView結(jié)合使用的方法
這篇文章主要給大家介紹了關(guān)于react-native組件中NavigatorIOS和ListView結(jié)合使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-09-09react?事項(xiàng)懶加載的三種方法及使用場(chǎng)景
這篇文章主要介紹了react?事項(xiàng)懶加載的三種方法及使用場(chǎng)景,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07react.js CMS 刪除功能的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇react.js CMS 刪除功能的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04react 跳轉(zhuǎn)后路由變了頁(yè)面沒(méi)刷新的解決方案
最近在學(xué)習(xí)React的過(guò)程中遇到了路由跳轉(zhuǎn)后頁(yè)面不刷新的問(wèn)題,本文就詳細(xì)的介紹一下解決方法,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06Create?react?app修改webapck配置導(dǎo)入文件alias
這篇文章主要為大家介紹了Create?react?app修改webapck配置導(dǎo)入文件alias,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12React-Router(V6)的權(quán)限控制實(shí)現(xiàn)示例
本文主要介紹了React-Router(V6)的權(quán)限控制實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05ReactNative頁(yè)面跳轉(zhuǎn)實(shí)例代碼
這篇文章主要介紹了ReactNative頁(yè)面跳轉(zhuǎn)的代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09理解react中受控組件和非受控組件及應(yīng)用場(chǎng)景
當(dāng)涉及到React框架時(shí),了解受控組件和非受控組件是非常重要的概念,本文主要介紹了理解react中受控組件和非受控組件及應(yīng)用場(chǎng)景,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01