正确使用classnames库的方式摸索【玩转React】
前言
我们日常开发使用的是React框架,主要采用JSX写法,而classnames与JSX十分般配,组合使用效果极佳,可以实现class的动态绑定。
接下来,通过对 classnames 源码的阅读,来进一步了解classnames出现的契机及其用法。
听说你叫 className
讲 classnames 之前,科普一点关于它「兄弟」 className 的知识点。
万物皆有源之 JSX
众所周知,在 Recat 中配合使用 JSX 语法。而 JSX 在语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称。
因此,在 React 中使用 className 为元素指定 CSS 的 class。
className 的两种用法
我们在 React 中是这样为元素添加样式的:
<div className="mt20">Hello World</div>
或者根据某个变量的值进行动态绑定,如下就根据 selected 的值判断是否为元素添加 active 样式:
<div className={`${selected ? 'active' : ''}`}>
{selectedText}
</div>
必有但是
动态绑定的方式确实让代码变得更加灵活,但是上面这种 ES6 模板字符串的写法,当有多个判断的时,会显得臃肿且不好维护。
那,有没有更好的实现方案呢?
classnames 出现的契机
每当遇到一个新知识点,我总是不由的想,它为什么会诞生?它帮忙解决了什么问题?
开发者需要什么?
从前面的文字中提取关键讯息,不难发现,开发者需要更简洁的绑定多个 className 的方式。
classnames 是什么?
而 classnames 源码的第一句介绍,正好符合开发者的需要:
A simple JavaScript utility for conditionally joining classNames together.
直译过来就是
一个简单的、有条件的绑定多个 className 的 JavaScript 实用函数.
classnames 的用法
用前先安装
classnames 是一个第三方 JavaScript 库,使用前需要先安装。
npm、bower、yarn三件套
# via npm
npm install classnames
# via Bower
bower install classnames
# or Yarn (note that it will automatically save the package to your `dependencies` in `package.json`)
yarn add classnames
语法
classnames 函数支持多个传参,参数的类型也支持数值、字符串、对象、数组等多种。
classnames(class1,class2,...classN)
用法很多样
基础用法
// 多个字符串 两种写法均可
classNames('mt10', 'font20') // => 'mt10 font20'
classNames('mt10 font20') // => 'mt10 font20'
//「字符串+对象」组合
classNames('switch', { selected: false }) // => 'switch'
classNames('switch', { selected: true }) // => 'switch selected'
// 对象 三种写法均可
classNames({ switch: true }, { selected: true }); // => 'switch selected'
classNames({ switch: true, selected: true }); // => 'switch selected'
classNames({ 'switch selected': true }); // => 'switch selected'
// 数组
classNames('font20', ['mt10', { switch: true, selected: false }]); // => 'font20 mt10 switch'
ES6 语法
支持动态类名
let type = 'disabled';
classNames('radio', { [`radio-${type}`]: true }); // => 'radio radio-disabled'
classNames('radio', `radio-${type}`); // => 'radio radio-disabled'
React 中使用
前面提到过 className 的知识点,React 中添加 class 使用 className。
import classNames from 'classnames';
const checkboxCls = classNames('checkbox-group', { 'checkbox-group-horizontal': true });
<div className={checkboxCls}></div>
总结
先来总结一下classnames的用法:
- classnames 支持多种写法。
- classnames 函数的入参是无序的,但是编写习惯是字符串类型的放前面,其他放在后面。
- classnames 函数会忽略入参中的错误值。
- classnames 函数支持动态类名。
对「CSS-in-JS」的思考
现状
由于我们项目几乎都用的 React 框架,而 CSS-in-JS 写法是如此丝滑。在 CSS 中使用 JS 变量,在基础组件的建设中很有帮助。
思考
很多事物带有两面性,CSS-in-JS 在拥有写法灵活和支持局部作用域的优势的同时,会增加运行开销和包大小。
有点像「鱼与熊掌」做选择的感觉,目前还比较难抉择。
替代
我读到了一篇文章,是Emotion 的第二大活跃维护者 Sam 分享《我们为何弃用 css-in-js》。这篇原文我没有办法打开,但是在掘金社区找到了译文,译文指路☞《为什么我们正在放弃 CSS-in-JS》
简单介绍一下这篇文章,文章前半部分介绍了 CSS-in-JS 的优缺点、复杂性。后半部分讲移除 CSS-in-JS 之后的新样式方案以及构建时 CSS-in-JS 方案看法。
带着这篇文章的结尾带来的启发,我开始考虑未来我们项目的改进方案。可能还需要多一些深入研究和局部实验之后才会有明确的答案。
作者:非职业「传道授业解惑」的开发者叶一一
简介:「趣学前端」、「CSS畅想」系列作者,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)