来源 | 愿码 (ChainDesk.CN) 内容编辑
愿码 Slogan | 连接每个程序员的故事
网站 | http://chaindesk.cn
愿码愿景 | 打造全学科 IT 系统免费课程,助力小白用户、初级工程师 0 成本免费系统学习、低成本进阶,帮助 BAT 一线资深工程师成长并利用自身优势创造睡后收入。
官方公众号 | 愿码 | 愿码服务号 | 区块链部落
免费加入愿码全思维工程师社群 | 任一公众号回复“愿码”两个字获取入群二维码
本文阅读时长:13min
以前使用 Create React App,你实际上没有很多选项可以直观地清理。经常处于随机级联样式表(CSS)项目维护者的心血来潮之中,并且试图让项目编译过程中涉及的其他库,框架或预处理器经常成为一场噩梦。
Create React App 上下文中的预处理器基本上是构建过程中的一个步骤。在这种情况下,我们讨论的是采用某些样式代码(CSS 或其他格式)的东西,将其编译为基本 CSS,并将其添加到构建过程的输出中。
在本文的篇幅中,我们将介绍涵盖与样式相关的功能的各种材料,并突出显示在我看来,Create React App 中最好的新功能之一:支持 CSS 模块和 SASS。
介绍 CSS 模块
CSS 模块能够以防止引入全局重叠命名空间的方式模块化你所导入的任何 CSS 代码,尽管最终结果仍然只是一个巨大的 CSS 文件。
更好的项目组织
让我们首先清理一下我们项目中的目录结构。我们要做的就是将每个具有 CSS 和 JavaScript 代码的组件分离到自己的文件夹中。先来创建 NewTodo,Todo,App,TodoList,和 Divider 文件夹,并将它们所有相关的代码放在其中的每一个文件夹中。
我们还需要在每个被调用的目录中创建一个新文件,该文件 index.js 只负责导入和导出相应的组件。例如,App 索引文件(src/App/index.js)将如下所示:
import App from “./App”;
export default App;
Todo(src/Todo/index.js)的新索引文件 如下所示:
import Todo from “./Todo”;
export default Todo;
你可以根据此模式猜测索引文件的内容 NewTodo,TodoList 以及它们的 Divider 外观。
接下来,我们需要更改引用这些文件的每个位置,以便更轻松地导入所有这些文件。不幸的是,这将是一些繁琐的工作,但我们需要做同样的事情,以确保我们不会破坏过程中的任何事情。
首先,在中 src/App/App.js,将 TodoList import 组件更改为以下内容:
import TodoList from “../TodoList”;
我们不需要做任何事情,Divider 因为它是一个没有导入的组件。NewTodo 并且 Todo 是类似的类型,所以我们也可以跳过它们。src/TodoList/TodoList.js 另一方面,我们需要处理很多事情,因为它是我们最高级别的组件之一并且进口很多:
import Todo from “../Todo”;
import NewTodo from “../NewTodo”;
import Divider from “../Divider”;
但那还不是全部。我们的测试文件 src/TodoList/TodoList.test.js 也需要修改为包含文件的这些新路径,否则我们的测试将失败!我们需要几乎与之前相同的导入列表:
import TodoList from “./TodoList”;
import NewTodo from “../NewTodo”;
import Todo from “../Todo”;
当你重新加载你的应用程序时,你的代码应该仍然正常工作,测试应该全部通过,一切都应该干净利落!我们的完整项目结构现在应如下所示:
src/
App/
App.css
App.js
App.test.js
index.js
Divider/
Divider.css
Divider.js
index.js
NewTodo/
NewTodo.css
NewTodo.js
NewTodo.test.js
index.js
Todo/
Todo.css
Todo.js
Todo.test.js
index.js
TodoList/
TodoList.css
TodoList.js
TodoList.test.js
index.js
index.css
index.js
setupTests.js
… etc …
将 CSS 模块引入我们的应用程序
如果我们想使用 CSS 模块,我们需要遵循一些简单的指南。首先,我们需要命名我们的文件[whatever].module.css,而不是[whatever].css。接下来我们需要做的是确保我们的样式简单命名并且易于引用。让我们首先遵循这些约定并将我们的 CSS 文件重命名为 Todoas src/Todo/Todo.module.css,然后我们将稍微改变一下内容:
.todo {
border: 2px solid black;
text-align: center;
background: #f5f5f5;
color: #333;
margin: 20px;
padding: 20px;
}
.done {
background: #f5a5a5;
}
接下来,我们将开放 src/Todo/Todo.js 以利用 CSS 模块。我们在我们的 Todo 组件中创建了一个辅助函数 cssClasses(),它返回我们应该在组件中使用的样式,并且我们不需要进行更改以使所有工作与之前完全相同。我们还需要 import 在顶部更改我们的语句,因为我们重命名了文件并且正在改变我们的 CSS 加载到代码中的方式!看看以下内容:
import styles from “./Todo.module.css”;
这使我们的代码可以 Todo.module.css 通过引用它们来利用定义的任何类名 styles.[className]。例如,在前一个文件中,我们定义了两个 CSS 类名:todo 和 done,所以我们现在可以通过 styles.Todo 和在组件中引用它们 styles.done。我们需要更改 cssClasses()函数才能使用它,所以让我们现在进行那些确切的更改。在 src/Todo/Todo.js,我们的 cssClasses()功能现在应该如下所示:
cssClasses() {
let classes = [styles.todo];
if (this.state.done) {
classes = […classes, styles.done];
}
return classes.join(‘ ‘);
}
保存并重新加载,我们的应用程序应该恢复正常!接下来,让我们更改组件 hr 内部的标签 todo 以拥有自己的样式和效果。返回 src/Todo/Todo.module.css 并为我们的 hr 标签添加以下块,我们将给出一个新类 redDivider:
.redDivider {
border: 2px solid red;
}
最后,返回我们的 render()函数 src/Todo/Todo.js,并将 render()函数的 hr 标记包含更改保存并重新加载,现在我们应该完全划分 CSS 代码而不必担心冲突和全局命名空间!这是输出的样子:
与 CSS 模块的可组合性
这并不是 CSS 模块给我们的全部,尽管它肯定是 CSS 模块的重要组成部分之一,我们立即得到并毫不费力。我们还获得了 CSS 可组合性,它能够从其他类继承 CSS 类,无论它们是否在主文件中。当您设置更复杂的嵌套组件时,这可能非常有用,这些组件都需要处理略有不同的样式表,但彼此之间并没有太大的不同。
假设我们希望能够将某些组件标记为关键组件而不仅仅是常规 Todos。我们不想对组件做太多改变; 我们希望它继承与所有其他 Todos 相同的基本规则。我们需要设置一些代码来实现这一目标。回到后面 src/Todo/Todo.js,我们将进行一些修改以允许一个名为的新状态属性 critical。我们将从 constructor 组件开始,我们将添加新 state 属性和 bind 函数标记:
constructor(props) {
super(props);
this.state = {
done: false,
critical: false
};
this.markAsDone = this.markAsDone.bind(this);
this.removeTodo = this.removeTodo.bind(this);
this.markCritical = this.markCritical.bind(this);
}
我们在 critical 属性中添加一个新属性,state 并将其设置为默认值 false。然后我们还引用了一个函数(我们还没有编写)markCritical,并且我们绑定了 this,因为我们稍后将在事件处理程序中使用它。接下来,我们将解决这个问题 markCritical():
markCritical() {
this.setState({critical: true});
}
我们还需要修改我们的 cssClasses()函数,以便它可以对这个新 state 属性做出反应。为了演示 CSS 模块的可组合性功能,我们将其设置 classes 为原来是一个空数组,然后第一个项目变为 critical 或 todo,取决于项目是否标记为 critical:
cssClasses() {
let classes = [];
if (this.state.critical) {
classes = [styles.critical];
} else {
classes = [styles.todo];
}
if (this.state.done) {
classes = […classes, styles.done];
}
return classes.join(‘ ‘);
}
最后,在我们的 render 函数中,我们将创建 button 标记以将项目标记为 critical:
render() {
return (
{this.props.description}
Mark as Done
Remove Me
Mark as Critical
);
}
我们还没有完成,尽管我们至少有 90%的方式。我们还想回到 src/Todo/Todo.module.css 并为 critical 类名添加一个新块,我们也将使用我们的可组合属性:
.critical {
composes: todo;
border: 4px dashed red;
}
要使用合成,您需要做的就是添加一个新的 CSS 属性,composes 并为其指定一个您希望它组成的类名(或多个类名)。在这种情况下,撰写是一种奇特的方式,它表示它继承了其他类名的行为,并允许您覆盖其他类名。在前面的例子中,我们说的 critical 是一个 CSS 模块类,它由一个 todo 模型作为基础,并添加 border 一个大的红色虚线的组件,因为,我们只是说这意味着它是关键的。
像往常一样保存并重新加载,您应该能够将项目标记为标记为完成,标记为严重或两者,或通过单击删除我删除它们,如以下屏幕截图所示:
这就是我们对 CSS 模块的简要介绍!在继续之前,您还需要通过在屏幕中点击 U 来快速更新测试快照 yarn test。
将 SASS 引入我们的项目
SASS 本质上是具有扩展功能支持的 CSS。当我在这里说扩展功能支持时,我的意思是它!SASS 支持以下功能集,CSS 中缺少这些功能集:
· 变量
· 嵌套
· 部分 CSS 文件
· 导入支持
· 混入
· 扩展和继承
· 运算符和计算
安装和配置 SASS
好消息是,在 Create React App 项目中获得 SASS 支持非常简单。我们首先需要通过 yarn 或安装它 npm。
$ yarn add node-sass
我们将看到它的大量输出,但假设没有错误并且一切顺利,我们应该能够重新启动我们的开发服务器并开始使用一些 SASS。让我们创建一个更通用的实用程序 SASS 文件,它将负责存储我们想要在整个应用程序中使用的标准化颜色,以及存储整齐渐变 hr 模式的东西,以防我们想在其他地方使用它。
我们还将更改我们正在使用的一些颜色,以便有一些红色,绿色和蓝色,这取决于项目是分别是关键,完成还是两者都不是。此外,我们需要稍微改变我们的项目,并添加一个新文件,以获得一些共享样式和颜色的概念。那么,让我们开始吧:
src/shared.scss 在我们的项目中创建一个新文件,并为其提供以下主体:
$todo-critical: #f5a5a5;
$todo-normal: #a5a5f5;
$todo-complete: #a5f5a5;
$fancy-gradient: linear-gradient(
to right,
rgba(0, 0, 0, 0),
rgba(0, 0, 0, 0.8),
rgba(0, 0, 0, 0)
);
接下来,跳转到 src/Divider/Divider.css 并将文件重命名为 src/Divider/Divider.scss。接下来,我们将更改对 Divider.cssin 的引用 src/Divider/Divider.js,如下所示:
import “./Divider.scss”;
现在我们需要更改代码 Divider.scss 以在我们的共享变量文件中导入并使用变量作为其中的一部分:
@import “../shared”;
hr {
border: 0;
height: 1px;
background-image: $fancy-gradient;
}
因此,我们在新的共享 SASS 文件中导入 src/,然后该 background-image 值只引用 $fancy-gradient 我们创建的变量,这意味着我们现在可以在需要时重新创建那个花哨的渐变而无需反复重写它。
保存并重新加载,您应该看到没有任何重大变化。
混合 SASS 和 CSS 模块
好消息是,在 Create React App 中将 SASS 引入 CSS 模块基本上并不复杂。事实上,这些步骤是相同的!所以,如果我们想要开始混合这两者,我们需要做的就是重命名一些文件并改变我们的导入处理方式。让我们看看这个行动:
首先,返回我们的 src/Todo/Todo.module.css 文件并进行一个非常小的修改。具体来说,让我们重命名它 src/Todo/Todo.module.scss。接下来,我们需要改变我们的 import 陈述 src/Todo/Todo.js,否则整个事情将崩溃:
import styles from “./Todo.module.scss”;
现在,我们应该让我们的 SASS 使用 Todo 组件的 CSS 模块,所以让我们开始利用它。再次,我们需要 import 我们的 shared 文件放到此文件 SASS 也。请注意以下内容 src/Todo/Todo.module.scss:
@import ‘../shared’;
接下来,我们需要开始更改对各种背景颜色的引用。我们将常规 Todos 的背景更改为 $todo-normal。然后,我们将完成的 Todo 背景更改为 $todo-complete。最后,我们要将 critical 项目更改为 $todo-critical:
.todo {
border: 2px solid black;
text-align: center;
background: $todo-normal;
color: #333;
margin: 20px;
padding: 20px;
}
.done {
background: $todo-complete;
}
.hr {
border: 2px solid red;
}
.critical {
composes: todo;
background: $todo-critical;
}
保存并重新加载我们的项目,让我们确保新的配色方案得到尊重:
现在,我们在 Create React App 项目中很好地集成了 CSS 模块和 SASS,而无需安装单个新依赖项。我们让他们一起玩得很好,这是一个更大的成就!