塑造React-JS应用程序的最佳方式

166 阅读16分钟

每当我们开始一个React-JS项目时,我们通常会讨论的一个问题是,在这个特定的项目中,我们应该遵循哪种样式设计方法。出于这个原因,我将讨论以下的样式选择,并解释每一种样式的优点和缺点以及我个人的喜好。

  • 内联样式
  • 全局样式文件
  • SASS/SCSS
  • CSS模块
  • CSS-in-JS

TL;DR:

我个人最喜欢的是 样式化的组件 (这是一个CSS-in-JS库),因为它对用户非常友好,支持度高,性能好,学习曲线平滑,同时具有动态样式和开箱即用的功能。综上所述,我建议阅读这篇文章,因为每个项目都有自己的用例,有时使用风格化组件可能会成为一种过度杀戮,或者有时你可能在不支持风格化组件的传统项目上工作。

简介

首先,在考虑造型方案时,我们需要考虑以下几个方面,我也会用这些来比较各种造型方案。

  • 可维护性
  • 可重用性
  • CSS功能,如伪类等。
  • 样式设计时使用JavaScript逻辑
  • 性能
  • 调试
  • 编码时的便利性
  • 项目规模

内联样式

内联样式是指你在JSX元素的 "style "道具中传递所有的样式。这些样式是作为一个JavaScript对象传递的,并采取我们在正常JavaScript中使用的任何变量。

const styles = {
    backgroundColor: 'red',
    color: 'blue'
}
return (<div style={styles}>some text</div>)

请注意,这些样式是以骆驼字母的格式出现的。此外,这些样式是以字符串的形式传递的。

优点。

  • 容易实现,特别是在小项目中
  • 不需要外部样式表,这意味着少了一个需要渲染的页面
  • 很容易在样式中实现JavaScript逻辑
  • 易于调试,只需从chrome开发工具中找到该元素并实现样式。
  • 如果你把数字作为一个值,React会自动转换为px。

缺点。

  • 极难重复使用和维护
  • 很多CSS功能不能在内联样式中实现,如伪类、伪元素、媒体查询、关键框架或其他高级功能,如嵌套样式等。
  • 在一个react应用中,有许多文件被渲染,所以所有的内联样式都会对性能产生负面影响。

总结

在我的应用程序中,我不喜欢内联样式,除非我的时间非常短(在这种情况下,我确保在生产前迁移到其他样式选项),或者我只是在构建一个小的组件或一个非常小的项目,这通常不是情况。例如,如果我做一个非常简单的计算器应用,我想展示我的技能,我不会费力地花太多的时间去做造型。

另外,由于内联造型是一个JavaScript对象,并且与react项目的状态兼容,你可以使用状态来操作小项目的造型。

全局CSS文件

全局样式是指当你的react项目有一个App.css或index.css文件时,你要为整个React项目建立一个样式文件。你在你的App.js中导入该样式文件

import React from 'react';
import './App.css';
import MyApp from './MyApp';
const App = (props) => {
   return <div className="app">
            <MyApp />
          </div>
}
export default App

你可以在任何组件中使用任何类。例如,在MyApp组件中。

import React from 'react';
const MyApp = (props) => {
   return(
    <div className="my-app">Hello</div>
   )
}

最后在你的App.css文件中,使用名为 "my-app "和 "app "的类来样式。

.my-app {
    background-color: red;
 }
.app {
    font-size: 16px;
 }

一些重要的启示。

  • 我们不是在每个组件中都专门导入样式表。我们只需要导入一次就可以了。
  • 我们只需在我们的组件中使用 "className "道具,我们就可以从任何地方访问它,或者我们可以说CSS样式表的范围是全球性的。我们可以从应用程序的任何地方访问CSS类。
  • 这些样式不像内联CSS那样在JavaScript中,而是以适当的CSS格式存在。

一些使用案例。

如果你想建立一个静态网页或一个小项目(例如:一个非常小的POS机等),并希望在一天内启动和运行,你要做的是使用简单的HTML、CSS和SASS来开发网页。对于类,使用实用类和带有BEM符号的SASS友好类。使用实用类进行基本样式设计,使用BEM符号样式进行特定组件的样式设计。

如你所知,SASS只是一个CSS预处理器,它在最后建立一个CSS文件。因此,在构建网页后,建立一个React-JS项目,并复制粘贴CSS文件作为全局样式表,并将该项目分发到React组件中。

然而,需要注意的是,这些项目是低维护或零维护的网站,对那些想要快速建立和运行网站的人很有用

点击这里查看关于这个用例的一个非常有用的教程。

优点。

  • 建立快速、小型项目的一个非常好的策略,需要较少的维护和低预算资源
  • 只有一个CSS文件需要渲染,而不是像CSS模块那样的许多CSS文件(后面会解释)。
  • 在小项目中实现样式非常快
  • 构建HTML CSS模板
  • 在ReactJS之外的vanilla JavaScript项目中感觉很舒服
  • 很好的提高前端开发技能,小的不太严重,因为你了解了先进的命名模式和传统的编码模式,没有花哨的库,是按照模板指南的纪律来做的。

缺点。

  • 极其难以维护
  • 增加新功能是一场噩梦
  • 只能满足特定的使用情况
  • 需要学习命名规则,否则会出现问题。特别是BEM符号和实用类。如果没有正确遵循,那么名称冲突是非常普遍的。
  • 没有JavaScript逻辑可以实现,因此动态样式设计是一个挑战。(我不支持在reactjs项目中使用var()。
  • 命名是非常困难的

结论。

如果你的客户希望在极短的时间内完成一个功能有限、页面数量极少的小项目,并且在讨论后发现客户的预算不多,不希望花钱维护这个应用,可能打算以后再做大的项目,你可以使用这种方法。

例如,你有一个figma设计的项目,你希望把它作为一个模板,并希望使用预先制作的模板来增加功能,那么这个选项是好的。然而,新功能的文档指南是必须的。

如果你想要一个普通的网站(例如一个管理面板),并且不想花时间去设计它,而你获得了html css模板。

另外,如果你害怕自己不精通实用类或BEM符号,而且你害怕项目规模会增加。另外,如果你希望你的样式与你的React组件相连,那么使用这种方法是大忌

SASS/SCSS

SASS是一个CSS预处理程序。简单来说,在生产之前,它把所有的代码编译成一个全局的CSS文件。当涉及到ReactJS时,我们使用npm安装SASS。

它处理sass文件并将其转换为样式表。它通常被称为 "具有超能力的CSS"。

SASS给了我们一个像程序员一样的感觉,同时造型。例如,它提供了函数、混合器、循环、变量、对象,甚至是简单的列表。它帮助我们在造型中创建一些动态逻辑。

新的开发者会迷上SASS,因为SASS有助于抽象出CSS中的许多复杂问题。例如,用伪选择来选择子元素在CSS中是一个挑战,但在SASS中则容易得多。同样,你也可以使用变量、不同的文件、架构和多个样式表。

一个非常重要的用例。

遗留项目不支持新技术,大部分都是用SASS完成的,因为新的开发者发现在SASS上工作很容易。因此,由于新的和没有经验的开发人员可以在大项目上工作,包括那些每天有超过5-6万用户的项目,它在经济上是非常有效的,因为你不需要巨大的资源来工作在大项目。

例子

例如,你有一个想应用于每个图标的样式,让我展示两种方式(CSS和SASS)。

CSS。

.icon-mail {
  background-image: url("/icons/mail.svg");
  position: absolute;
  top: 0;
  left: 0;
}

SASS。

@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
  .icon-#{$name} {
    background-image: url("/icons/#{$name}.svg");
    position: absolute;
    #{$top-or-bottom}: 0;
    #{$left-or-right}: 0;
  }
}

@include corner-icon("mail", top, left);

优点。

  • 学习曲线非常平滑,在CSS之后非常容易学习
  • 涉及到学习数组、对象、导出、项目文件夹结构、逻辑、混合器、函数、嵌套样式,这反过来帮助我们有一个编程和算法思维的介绍,而不是在原始CSS之后马上学习JavaScript。
  • 传统的项目和基于类的组件通常使用SASS的样式,由于SASS在语法上没有太多的突破性变化,甚至超过5年的项目也在使用SASS作为他们的样式解决方案。因此,学习SASS是一笔巨大的财富。 另外,旧版本的React不支持现代库,如情感或风格化组件。甚至有单独的Web Pack配置的CSS模块。
  • 由于很多遗留项目是用SASS完成的,另一个优势是巨大的社区支持和对许多已知问题的修复。
  • 有了常量和CSS上面的所有超强功能,如果操作得当,它可以帮助你为项目建立主题,甚至在规模上。

缺点。

  • 尽管SASS在其样式中包含了逻辑,但它仍然没有办法将JavaScript包含在它的样式中。因此,你需要依赖条件类名来应用动态样式。 你可以按照 这个堆栈溢出线程 来了解如何在SASS中使用CLSX条件渲染样式
  • 在了解基本结构之前,需要了解SASS的完整逻辑
  • 即使这是第一次,由于SASS依赖于主题构建的实用类和BEM符号,调试 在SASS中成为一个挑战。
  • 调试一个肮脏的架构是一场噩梦。想象一下,调试一个建立在SASS上的React应用,并且由一个还不知道最佳实践和文件夹模式的人(甚至是你)开发。由于SASS与上面提到的浏览器开发工具不兼容,你会变得很吃力。
  • 需要有BEM和实用类的知识才能有效实现。
  • 由于SASS在遗留项目中被大量使用,你有可能会去调试一个以不良编码方式实现的项目。特别是由于SASS普遍受到初学者的喜爱。
  • SASS对性能要求很高,因为所有的代码在生产前都要被编译成CSS样式表。
  • SASS与其他React库不兼容
  • 类名可能发生冲突

总结。

尽管我提到了所有的缺点,但由于我提到的优点,用反应学习SASS是一笔巨大的财富。这有助于我们在拥有大量 用户的遗留项目中获得经验,从而帮助我们理解遗留的React项目中使用的编码模式,即基于类的组件,没有许多外部库。那些项目有经验丰富的开发人员在他们的团队中工作,所以你可以工作,从而向他们学习。

我不希望在我的项目中使用SASS,因为它与React组件缺乏联系。我知道如何使用clsx将状态有条件地传递到样式中,使其动态并与我的反应状态兼容。然而,当我讨论CSS-in-JS库,如情感或风格化组件时,你会知道用它们来动态样式是多么容易。

CSS模块

所有的CSS文件都有全局范围。这意味着错误地过度使用类名是非常常见的。因此,使用CSS模块,你的本地CSS文件只对所需的JSX组件有范围。

例如,如果你有一个叫做Component.jsx的文件,那么为了建立它的样式文件,你需要把它改名为.module.css。如Components.module.css

现在用一个变量名导入这个文件。比如说。

import styles from './Component.module.css'

现在把类的名字作为一个变量传递。例如,在你的Component.module.css文件中,如果你有。

.button {
    background: red;
}

然后在你的Component.js中使用这个按钮类作为。

import React from 'react'
import styles from './Component.module.css'
const Component = (props) => {
     return (<div className={styles.button}>Hello</div>
}
export default Component

现在在幕后react会给这个类一个唯一的名字,因此如果你在地图的其他地方使用这个按钮类,名字就不会发生冲突。

这是对全局CSS和SASS的一个重大改进,因为有了本地的类名。因此,如果你想建立可重复使用的UI对象,只需建立与该组件相对应的module.css文件。因此,这降低了组件重用性的复杂性,因为它只连接到一个可重用的React组件,以及由于没有名称冲突的可维护性。

优点。

  • 支持可重用的React结构。如果其对应的组件是可重用的,那么该样式也是可重用的。
  • 没有名称冲突,因此可维护性好
  • 项目规模小,与SASS相比,性能好。
  • 对于新的开发者来说,可以通过基于类名的重写样式来改进特定的组件。

缺点。

  • 与组件状态的联系为零,因此,内部没有逻辑模式。
  • 对于传统的react项目来说,涉及到Web Pack的具体配置,这对新的开发者来说是很烦人的学习。
  • 不能使用JavaScript
  • 由于对象结构,很难将多个类附加到单个组件上。可以使用Array.join(),跟随这个堆栈溢出线程来学习。然而,这应该被避免。
  • 由于高级开发人员选择了其他的造型方式,所以社区的支持较少。(SASS或CSS-in-JS)。
  • 与主题不兼容
  • 不具备可扩展性

如果你想把CSS模块和SASS结合起来,请看这个教程

总结。

如果我收到一个项目,而且我的期限很短,我想通过覆盖样式快速修复小的设计错误,我会使用CSS模块。除此以外,我不会选择CSS模块,因为其他的样式选项提供了更多的好处

CSS-in-JS

CSS-in-JS是一个造型选项,你可以在JavaScript文件中使用CSS,并作为一个类传递。其过程是,你用JavaScript将样式传递给一个元素,然后编译器将其转换为CSS,并相应地附加上。

有很多基于CSS-in-JS框架的库(我已经附上了带有名称的文档页面),比如。

当我们谈论CSS-in-JS时,需要注意的是,有很多库可以实现这一功能。然而,我个人最喜欢的是Styled组件。应该指出的是,CSS-in-JS都提供了几乎相同的功能,它是最需要的造型方式。唯一的区别在于语法和数据的传递方式。因此,我最喜欢样式化组件,因为它的语法是最简单的。然而,在样式化组件中,你要为你的组件命名,而不是像JSS或情感那样将样式作为道具传递。因此,使用风格化组件的一个小缺点是,你可能会在命名你的风格化组件时遇到困难。

一些需要思考的重要问题

Material-UI第4版采用JSS来覆盖样式。因此,如果你在一个不那么传统的项目中,其中有Material-UI 4版本,那么最好选择JSS库。

此外,在他们最近的MUI-5更新中,他们突然从JSS转向了风格化组件。因此,如果你正在使用MUI的最新项目中工作,那么对风格化组件的了解是一个重要的 优势。

最后,在幕后,MUI使用情感来构建它的风格化框架,因此,情感的知识是非常有帮助的。

此外,在具有服务器端渲染的项目中,样式化组件不被处理,因此在具有服务器端渲染的项目中覆盖样式,最好使用 emotion。这里给出了这个问题的链接。

优点。

  • 在CSS-in-JS的方法中,存在着最现代的反应应用程序的样式的使用案例。
  • 你可以直接在你的造型方案中使用主题和很多其他的状态和道具。
  • 对于使用变量(甚至是主题),你可以使用箭头函数语法来传递它们,这与 react 语法是一致的。此外,这遵循了现代的功能范式,因此对用户非常友好。
  • 支持服务器端渲染,甚至有typecript支持。
  • 在CSS-in-JS方法中启用了懒人加载,由于这种方法只在需要时加载样式。这是对性能的一个重大提升
  • 与所有的现代库兼容
  • 它有来自SASS和JavaScript的所有功能,因此提供了两个世界的最佳选择。此外,所有的逻辑都在JavaScript中完成,所以你不需要学习任何额外的语法(如SASS)来执行逻辑。
  • 风格化组件具有最平滑的学习曲线和最新的文档。
  • 可以有许多不同类型的架构
  • 极具可扩展性,非常容易维护
  • 不会因为局部范围而发生名称冲突
  • 良好和活跃的社区

缺点。

  • 由于浏览器开发者工具中的独特类名,有点难以调试
  • 与旧的ReactJS版本不兼容,因此在传统项目中不是很常见。即使低于React v16,你也开始有一些主要的兼容性问题。
  • CSS-in-JS将所有的样式定义解析成普通的CSS,并将所有的东西放在index.html文件的样式标签中。这将增加html文件的大小。
  • 我们不能使用其他的CSS工具,如SCSS,LESS和PostCSS。

总结

我通常在90%的应用程序中使用CSS-in-JS的方法(主要是风格化的组件)。其余的10%是那些非常小的应用,我需要快速的解决方案,并且不需要太多的JavaScript参与我的CSS。然而,在较早的ReactJS项目中,特别是那些应用程序是建立在基于类的组件上的,我会选择SASS。

人们会问一个问题:CSS-in-JS和内联样式有什么区别?CSS-in-JS为我们提供了类的名称,而内联样式则直接将样式注入HTML元素的样式属性中。因此,内联样式对性能不友好,也有很差的特异性指数。