组件库的选择

我们现在开发应用,几乎不会完全从零去编写样式。因为目前所有的主流 UI 框架都是组件驱动的,包括 React。那么我们完全可以将一些通用的功能封装成组件,小到按钮,大到表单。这样我们在需要使用它们时就不用再去重新开发,可以节省大部分时间成本,让我们专注于业务逻辑上。集合了很多组件的库就是组件库。

开源的第三方组件库非常多,令人眼花缭乱,你可能不知道该怎么去选择。

我在这里对常见的几个开源组件库进行比较,它们分别是 Google 开源的 Material UI、蚂蚁金服开源的 Ant Design 和社区开源的 Chakra UI。

Material UI 和 Ant Design 其实比较相似,都有各自的设计语言,需要遵循设计规则。它们的优点在于提供了功能非常丰富的组件,在开箱即用这一点上有着非常明显的优势。

Chakra 的优点是易于修改和定制。Chakra 不受任何设计系统的约束,所以在自定义样式方面,它非常自由。

很多开发者喜欢使用 Material UI 或者 Ant Design 的一个主要原因就是开箱即用。但是随着应用的复杂度不断增高,开发者很快就会陷入到组件默认样式和自定义样式的斗争中。而且越复杂的样式定制,定制成本越高。

具体选择哪一个组件库,其实没有绝对的标准。

通过项目类型、开发者自身的经验以及和设计师去沟通,大概能预测到这个项目的样式自定义复杂程度。

如果项目不复杂,但是自定义样式的需求比较多,建议选择 Chakra。

如果项目非常复杂,但是自定义样式的需求不多,建议选择 Material UI 或者 Ant Design。

如果项目的自定义样式非常高的话,也可以选择自研组件库。

我们要开发的图灵鸟网站属于不复杂,但是有一定自定义样式需求的项目,所以选择 Chakra 就很适合。

样式方案的选择

当然只使用组件库是不够的,在项目的开发过程中我们还需要编写一些自定义的样式。

在 React 中可以选择的样式方案也有很多,比如 Sass/Less/Stylus 这类预处理器;styled-components/emotion 这类 CSS-in-JS 框架;以及 Tailwind CSS/unocss 这类 CSS 框架。

样式预处理器的优点是功能强大,让编写样式也具有了一定的编程性。缺点是学习成本较高。

CSS-in-JS 这类框架的优点是可以直接在 JS 中以组件的方式编写样式,比较灵活。缺点是比较繁琐,和直接写 CSS 很相似。

CSS 框架的优点是简单,学习成本低。缺点是功能没有样式预处理器那么多。

选择样式方案和选择组件库是一样的,没有绝对的标准,也要考虑多方面因素。

我本人很喜欢 TailwindCSS,在这里我把 TailwindCSS 吸引我的点再详细介绍一下。

不用再考虑为类命名

计算机的世界里有两大致命难题,其中一个就是命名。编写样式规则并不难,难的是为 class 命名。
在项目开发的过程中,你需要为 class 命名这件事考虑下面几个问题:

  • 我们团队该用什么命名规范?BEM 还是什么?
  • 这个样式会多次使用吗?
  • 多次使用这个样式是否额外需要处理兼容问题?
  • 我会和其他样式组合使用它吗?会不会有冲突?

如果你在开发一个小型项目,或许不需要为这些问题烦恼。但如果你在开发一个具有上百个页面的大型复杂应用,你必须考虑这些事情。因为项目中的样式代码并不是一个人在用,而是要和团队成员一起使用。这会形成很大的认知负担。
TailwindCSS 解决了这个问题,我们完全不需要为 class 命名。一切 class 都是直观的。

不需要在样式文件和 HTML 文件之间切换

如果你的样式文件和 HTML 文件是分离的,那么在开发过程中,你需要频繁地切换文件。这是一件很花费时间和容易分散注意力的事。
在 TailwindCSS 中,因为我们的样式都是内嵌到 HTML 中的属性,所以不需要进行文件的切换,这会显著提高我们的开发效率。

不需要关注选择器优先级

在传统的样式解决方案中,我们可能会碰到各种让人烦躁的样式冲突问题。特别是当我们的 DOM 结构非常复杂,那就难免会写出很多复杂的选择器。而选择器是有优先级的,复杂的选择器,很容易就会让样式发生意外。甚至有时我们会选择使用 !important 来解决问题,但这样的后果是让样式的维护变得更加复杂。
TailwindCSS 在这一点上做得非常好,因为它只需要关注当前的元素,你想修改样式,只需要改它的样式,不会对其他元素造成任何影响,所以也就没有选择器优先级问题。

以内联的方式使用媒体查询、伪类选择器、子选择器

传统的内联样式有一个问题,就是不能使用媒体查询、伪类和子选择器。
如果你在开发响应式应用,你需要编写媒体查询,并在其中为某些元素创建不同的选择器,这很麻烦。
TailwindCSS 可以将媒体查询、伪类选择器等全部用内联的方式使用,不需要单独编写复杂的媒体查询/选择器代码。

天然的 CSS 体积优化

如果你维护过非常大的样式表,你应该会碰到这个的问题:一堆乱七八糟的样式,但是你不敢删,因为你不知道到底有没有某个页面在用它。
在 TailwindCSS 中,它会在构建过程生成你项目中所用到的 CSS,不会有任何一条多余的样式出现。而且它会最大可能复用样式,让样式的体积始终处于最小的状态。

非常容易维护

和上面的所有理由相比,TailwindCSS 最大的优势在于非常好维护。
我们可以肆无忌惮的修改某个页面或者某个组件的样式,而不用担心会不会有什么额外的影响。
这和传统的样式解决方案是不同的。
在传统的样式解决方案中,我们修改某个样式,可能需要在一堆文件中查找,会不会破坏某些东西,或者引起样式冲突。而修改之后的测试和验证将会更难。
这就是传统样式解决方案的问题:会让样式的维护难度随着项目的复杂度增加而一同增加。
但 TailwindCSS 不会受项目的复杂度影响。无论是 1 个人开发 10 个页面的项目,还是 100 个人开发 1000 个页面的项目,样式的维护难度几乎都是一样的。

安装与配置 Chakra UI

在上一节的基础上,我们来安装 Chakra UI。

Chakra UI 的安装与配置非常简单,只有两步:

1. 安装依赖

在终端运行以下命令:

  1. npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6

之所以需要安装这么多包,是因为 chakra-ui 和 emotion 和 framer-motion 是对等依赖的关系。

2. 注入 ChakraProvider 组件

在使用组件之前,我们首先要在根组件中注入 ChakraProvider。

Nextjs 中的所有组件,最终都会被 pages/_app.tsx 所包裹。所以我们需要在这里进行注入。

  1. import "../styles/globals.css";
  2. import type { AppProps } from "next/app";
  3. import { ChakraProvider } from "@chakra-ui/react";
  4. function MyApp({ Component, pageProps }: AppProps) {
  5. return (
  6. <ChakraProvider>
  7. <Component {...pageProps} />
  8. </ChakraProvider>
  9. );
  10. }
  11. export default MyApp;

注入完成之后,我们在 pages/index.tsx 中添加一个最常见的按钮组件试试看。

  1. // other code...
  2. import { Button } from '@chakra-ui/react'
  3. // other code...
  4. const Home: NextPage = () => {
  5. return (
  6. // other code...
  7. <Button>Hello, Chakra UI!</Button>
  8. )
  9. }

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图1

这样页面上就会出现一个 Chakra UI 的按钮了!

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图2

如果你细心的话,应该也能发现字体的样式也发生了略微调整,这也是由 ChakraProvider 来处理的。

到这里 Chakra 的安装及配置就完成了。

安装与配置 TailwindCSS

接下来我们安装 TailwindCSS。

在 Nextjs 中配置好 TailwindCSS 共分五步。

1. 安装依赖

在终端运行如下命令:

  1. npm install -D tailwindcss postcss autoprefixer

tailwindcss 建议与 postcss、autoprefixer 一起使用,这样可以解决很多浏览器样式属性前缀问题。

2. 初始化配置文件

安装成功后在终端运行 tailwindcss 提供的初始化命令:

  1. npx tailwindcss init -p

该命令会在项目根目录下创建出 tailwind.config.js 和 postcss.config.js 两个配置文件。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图3

3. 配置模板路径

打开 tailwind.config.js 文件,可以看到它导出了一个对象。

该对象的 content 属性,就是 tailwindcss 编译的文件目录。我们在其中增加如下内容:

  1. module.exports = {
  2. content: [
  3. "./pages/**/*.{js,ts,jsx,tsx}",
  4. "./components/**/*.{js,ts,jsx,tsx}",
  5. ],
  6. // other code...
  7. }

4.将 TailwindCSS 的指令添加到 CSS 文件中

tailwindcss 提供了很多指令,这些指令具有不同的作用。

将 /styles/globals.css 中的内容替换为下面的代码:

  1. @tailwind base;
  2. @tailwind components;
  3. @tailwind utilities;

现在 TailwindCSS 的配置就完成了。

我们可以尝试使用 tailwindcss 的功能。修改 pages/index.tsx 中的第 18 行代码。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图4

可以看到浏览器中的 h1 标签字体大小和粗细都发生了变化。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图5

VSCode 智能感知插件

为了提高 Tailwind 的开发者体验,Tailwind 官方提供了 VSCode 插件:Tailwind CSS IntelliSense

这款插件有很多功能。

比如可以帮助我们自动完成 Tailwind Class 的输入。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图6

可以帮我们检查潜在的错误。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图7

text-4xl 和 text-3xl 样式冲突了,class 下方会出现绿色的波浪线。

当我们把光标悬浮在样式上时,可以帮我们自动显示对应的 CSS 代码。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图8

它还可以帮我们代码高亮,比如下方的颜色。

如何使用 TailwindCSS 和 Chakra-ui 做样式解决方案? - 图9