AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

ReactJS 中的 CSS 架构

  • 2017-08-15
  • 本文字数:3253 字

    阅读完需:约 11 分钟

我们生活在一个新的时代,每一天都充满了各种各样的新工具和范式。我们总是试图将旧有的架构应用在新技术上,而那样极可能以失败告终。 其中的一个例子便是 BEM—— 一个 CSS 命名约定,它解决的是那些可能不会再次出现的问题。

先来讲一讲重要的背景知识。

BEM**** 是什么?

BEM 是 CSS 的一个命名约定,遵从简单而直接的哲学:代码的一致性、伸缩性和可重用性。这个方法论正是源于它的名字:Block-Element-Modifier。这意味着所有的类会被拆分成三个实体,每一个实体在架构和代码组织上都具有不同的目的和角色。

  • 块(Block)****: 具备独立逻辑和功能的组件。
  • 元素(Element)****: 块中没有独立意义的部分。
  • 修改器(Modifier)****: 定义块或元素的行为和外观。

当讨论遵从 BEM 规范的选择器时,有以下三条规则:

  • 只使用 CSS 类选择器。
  • 类名可以包含数字但不应该包含特殊字符。
  • 使用连字符来分隔单词。

BEM 实体应该是这样的:

复制代码
/* 块的名字,也是块中元素和修改器的命名空间 */
.block
/* 块的命名空间后面紧跟下划线和元素名字 */
.block__element
/* 块或者元素的命名空间后紧跟连字符和修改器的名字 */
.block--modifier,
.block__element--modifier

为什么要使用BEM

BEM 哲学的提出基于以下几个前提:代码的一致性、代码的伸缩性、代码的可重用性、生产力和团队协作。从 BEM 的哲学出发,不得不说 BEM 是非常好的范例,并且已经在全球范围内被来自大公司(如 Google 和 Twitter)的许多开发者所采用。

如果想要了解关于这个方法论更多的信息,可以阅读这篇文章: CSS Architectures

让我们开始吧

当谈到代码的命名规范和代码结构时,不得不提到 BEM。BEM 很简单并且功能完善。然而,当谈论到 CSS 架构时还有另外一点必须考虑,那就是目录结构。于是我们不得不提到另一种架构:ITCSS

ITCSS 是由 Harry Roberts 提出的一个方法论,用于创建、管理和衡量大型的 CSS 项目。他曾说:

ITCSS__ 是一种方法论,旨在将整个 __CSS__ 项目可视化为一个分层的倒置三角形。这种分层架构代表了一个模型,可以帮助你以最有效、最节省资源的方式使用 __CSS_。_

本文不会深入探讨这个方法论,不过我们推荐阅读 Harry 的文章以掌握其背后蕴含的概念。简而言之,ITCSS 主张以分层的方式组织代码,以倒三角的方式组织结构,这样我们就可以在顶层定义通用元素,在底部定义特定元素。

这里的关键在于我们可以使用分层的方式作为一种有效的目录结构来组织代码。在我之前的经验中,我所使用的方法与其提出的原始目的有一点不同,我会用以下的方式对代码进行分层:

  • Settings: 基本配置和变量。
  • Tools: 函数和 mixins。
  • Base: 应用到每一个页面的基本样式。在这里放置 reset/normalize 的代码最好不过了。
  • Components: 组成界面的 UI 组件。
  • Utilities: 非常具体的规则,这是唯一可以使用!important 的层。

现在我们需要做的事情是混合这两个方法,然后一个强大且简单的 CSS 架构便唾手可得。

ReactJS**** 的方式

在过去几年中,BEM+ITCSS架构满足了我们所有的需求,直到一切都开始发生变化。当 ReactJS 成为主要的单页面应用库,以组件化进行思考的方式较以前便有些不同。现在,每一个组件是一个 JS 模块,并且每个模块中的 HTML 结构完全关联该组件,并且通过自定义属性可以动态变更组件状态和变量。不再需要将样式标签与语义化的 HTML 结构关联起来,现在你可以创建完全逻辑化的动态功能性组件。

所以在新的场景下我们怎样处理样式和代码结构呢?保持样式和 React 组件相分离,使用 BEM+ITCSS 方法,或者彻底改为使用CSS-in-JS方式?我会建议介于这两者之间,并且利用我们之前所积累的知识。

Think-Adapt-First**** 方式

使用这些方法论和命名约定的想法源于以下原因:保持样式隔离、创建具有唯一性的选择器并在组件作用域内理清选择器之间的关系。人们使用BEM约定并不是因为他们喜欢使用双下划线或双连字符,而是因为 BEM 有助于提升代码的一致性、伸缩性、可重用性、生产力和可预测性。这些都是可行性的前提,所以为什么不一直用它呢?

因为我们不能。当我们决定在项目中引入React时架构发生了改变。于是,一些限制、模式和新的可能性出现了。这是将我们以前的规则应用于新环境的最佳时机。下面是我强烈推荐给你的工具。

CSS**** 模块

为了说明 CSS 模块的所有优势和功能,我想引用其作者 Glen Maddern 的话。除了它能够带来成堆的好处,最主要的就是CSS**** 本地作用域。现今,所有的 React 组件都可以在逻辑和呈现状态上进行完全的隔离。下面是代码结构的直观显示:

在 style.css 中不再需要保持经典的 BEM 约定。依据 BEM 约定,我们应该将第一个实体作为组件的命名空间,但是现在有了 CSS 模块,这种关系会基于 JS 组件名进行动态的创建。

复制代码
/*
* Reset
*/
.button {
appearance: none;
border: 0;
background-color: white;
cursor: pointer;
color: #333;
font-size: .9rem;
font-weight: bold;
}
.button:focus,
.button:focus:hover {
border-color: #51a7e8;
box-shadow: 0 0 5px rgba(81, 167, 232, .5);
outline: 0;
}
/*
* Sizes
*/
.small {
padding: .5em 1.4em;
}
.medium {
padding: .8em 1.4em;
}
.large {
padding: 1.2em 2.2em;
}
/*
* Themes
*/
.default {
border: 1px solid #ddd;
border-radius: 3px;
background: linear-gradient(to bottom, #fefefe 0%, #ddd 100%);
}
.default:hover {
border-color: #bbb;
background: #ddd;
}
.default:active {
border-color: #aaa;
background: linear-gradient(to bottom, #bbb 0%, #ddd 44%);
}

按照规则,你的组件中应只包含需要的类。我们可以通过下面的方式来描述一个按钮:

复制代码
import PropTypes from 'prop-types'
import React from 'react'
import styles from './styles.css'
export const ButtonType = {
BUTTON: 'button',
RESET: 'reset',
SUBMIT: 'submit',
}
export const ButtonTheme = {
DEFAULT: 'default',
POSITIVE: 'positive',
DANGER: 'danger',
}
export const ButtonSize = {
SMALL: 'small',
MEDIUM: 'medium',
LARGE: 'large',
}
const Button = ({ type, onClick, children, theme, size }) => {
const className = `${styles.button} ${styles[theme]} ${styles[size]}`
return ({children})
}
Button.propTypes = {
type: PropTypes.oneOf(Object.keys(ButtonType)),
theme: PropTypes.oneOf(Object.keys(ButtonTheme)),
size: PropTypes.oneOf(Object.keys(ButtonSize)),
onClick: PropTypes.func.isRequired,
children: PropTypes.node.isRequired,}
Button.defaultProps = {
type: ButtonType.BUTTON,
theme: ButtonTheme.DEFAULT,
size: ButtonSize.MEDIUM,
}
export default Button

好的,下面我们给出组件分层的解决方案。那么如何定义全局样式呢,比如设置、规范化和重置?

ITCSS**** 复活

既然基于 ITCSS 的分层目录结构仍然可以完美匹配我们的需求,那么为什么不继续使用它呢?

上面的想法是在src**** 目录中创建与 ITCSS 同风格的样式文件目录,除了组件的文件目录外,因为 React 已经默认定义了组件的文件目录结构。

现在,我们会得到下面的目录结构:

我们可以使用:global标签在主应用程序中导入样式文件,样式可以作为全局的类来使用。

再应用Think-Adapt-First方式

该结构背后的理念是通过以一种可伸缩的方式保持CSS**** 架构创建更好的 ReactJS 项目,可以支持成千上万的组件和开发人员协同工作。

然而本文的真正关键点在于打开你的思维,去适应新事物!有时候适应是很困难的,因为对于难以掌控的事物,你必须放手,但是请不要忘记,你已经解决的问题可能将以一去不复返。

所以,年轻的朝圣者们,请持续探索知识。

查看英文原文 CSS Architecture with ReactJS


感谢薛命灯对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-08-15 19:004961

评论

发布
暂无评论
发现更多内容

自动动手制作一款Chrome扩展,一键转存文章

悟空聊架构

Nooka:将书籍生成可互动音频,支持随时打断和提问;Sam Altman:语音与图形界面结合将带来创新丨日报

声网

刷脸购物、智能补货:英特尔AI技术重塑零售门店体验

E科讯

全新 Graviton4 实例,提升 Valkey 性价比

亚马逊云科技 (Amazon Web Services)

成功案例丨从草图到鞍座:用先进的发泡成型仿真技术变革鞍座制造

Altair RapidMiner

仿真 CAE Inspire 工业仿真 发泡成型

【YashanDB 知识库】JDBC 查询 date 字段不返回时分秒?别只用 getString!

数据库砖家

数据库

用 AI 快速开发一款小程序

悟空聊架构

CodeBuddy首席试玩官

图形化编程语言视域下iVX开发平台的技术建构

代码制造者

ide 低代码

黑龙江等保:跨省或全国联网运行的网络系统如何选择备案地?

黑龙江陆陆信息测评部

LED屏幕天花板安装:打造炫酷空间的实用指南

Dylan

商业 LED LED display LED显示屏 LED屏幕

VMware ESXi 8.0U3e macOS Unlocker & OEM BIOS 集成驱动版,新增 12 款 I219 网卡驱动

sysin

esxi

vivo 互联网研发效能关键技术与实践

vivo互联网技术

DevOps 研发效能 CI/CD 测试工具

CST如何快速获得微带线或带状线简单分析模型

思茂信息

cst CST软件 CST Studio Suite

Arthas ognl(执行ognl表达式)

刘大猫

人工智能 监控 Arthas 监控工具 ognl

研发流程走出低谷,靠老一套肯定不行了

禅道项目管理

运维 开发 研发流程 禅道项目管理软件 禅道DevOps解决方案

CodeBuddy 开发者福音!在线简历0元搞定,再也不怕面试翻车!

不惑

CodeBuddy

入门无压力,进阶有深度:iVX 的开发者友好性双重法则

代码制造者

低代码 无代码

等保测评公司:备案证明

黑龙江陆陆信息测评部

等保测评:五级等保系统?

黑龙江陆陆信息测评部

一物一码赋能智能制造:MES如何实现生产全流程数字化追溯

万界星空科技

mes 一物一码 二维码系统 产品二维码管理 二维码追溯

快手上线鸿蒙应用高性能解决方案:数据反序列化性能提升90%

HarmonyOS开发者

【YashanDB 知识库】Mybatis-Plus 如何正确配置分页?Oracle 和 MySQL 写法都能用!

数据库砖家

数据库

Arthas mbean(查看 Mbean 的信息)

刘大猫

Java 监控 Arthas 监控工具 mbean

观测云:从云时代走向AI时代

观测云

人工智能

如何用AI工具制作毕业答辩PPT?PPT制作保姆级攻略来袭!

职场工具箱

效率工具 PPT 毕业设计 办公软件 AI生成PPT

应对亚马逊面试的有效方法

Nackydeng

程序员面试 大厂求职 北美求职 亚马逊面试 亚马逊面经

VMware ESXi 8.0U3e macOS Unlocker & OEM BIOS HPE (慧与) 定制版

sysin

esxi

VMware ESXi 8.0U3e macOS Unlocker & OEM BIOS ConnectX-3 网卡定制版

sysin

esxi

Uniapp开发鸿蒙购物项目教程之样式选择器

幽蓝计划

原生 iOS App 开发的优势

北京木奇移动技术有限公司

软件外包公司 APP外包 APP开发公司

接单拒绝别人最好的办法就是:“这个我不会做”

程序员郭顺发

ReactJS中的CSS架构_语言 & 开发_Douglas Gimli_InfoQ精选文章