59

React中编写CSS的姿势

 4 years ago
source link: https://www.tuicool.com/articles/miAJVvF
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在任何环境之下其实没有最佳,最有最适合,那么在React中编写CSS也是类似的。在React中有很多编写CSS的方式,在社区中讨论最多的应该是CSS In JS 和 CSS Modules。前段时间在《 React中CSS Modules的使用 》一文中探讨了在React中怎么使用CSS Modules来管理组件和项目的CSS。事实上,使用CSS Modules还是存有一定的缺陷。这篇文章将会和大家一起聊聊React中编写CSS的姿势,然后再会花一些篇幅来讨论CSS Modules编写CSS的最佳姿势。

React中编写CSS的系列痛点

其实我自己在React中编写CSS并不多,因为以前都是基于Vue的体系来做项目。现在切换到React技术栈,尝试着使用React来构建项目和组件库。到目前为止,我在项目React中使用过两种方式编写CSS:

  • 原生CSS结合处CSS处理器(Sass和PostCSS):该方式样式易于全局污染,多人协作易于发生冲突
  • 使用CSS Modules编写CSS,相比原生CSS是舒服多了,但引用组件库(独立库)就有点蛋疼,组件库样式覆盖令人头疼

这只是自己初步的感觉。但@Vjeux在分享CSS-in-JS时就抛出了React中编写CSS时令人头痛的一系列问题:

  • 全局污染 :在CSS中,选择器的作用域概念并不太强,其机制虽然方便我们重写样式,但也带来痛楚,易于污染全局
  • 命名混乱 :在多人协作(有的时候甚至是自己个人)在维护或开发一个项目的时候,容易造成样式冲突;而且命名混乱,难于维护。虽然BEM可以这种现象更好些,但还是难于避免命名的混乱,特别是在样式多变的情况之下
  • 依赖管理不彻底 :组件应该是相互独立的,在引入一个组件时,应该只引入组件所需要的样式。但现在的做法是除了要引入JavaScript之外,还需要引入组件的CSS。不过组件自身无法彻底的管理相关的样式依赖。当然,到目前为止,Webpack的一些 loader 可以让这方面有所改善
  • 无法共享变量 :复杂组件要使用JavaScript和CSS来共同处理样式,比如通过状态来动态更改样式风格。这样就需要通过JavaScript来处理CSS,就会造成有些变量在JavaScript和CSS中冗余。有可能CSS自定义属性会让这方面有所改变,但需相关验证

第一感觉,就编写CSS而言,在Vue的体系下要比在React的体系下爽多了。

React中编写CSS常见的方式

在React社区中有关于如何在React中编写CSS的讨论也非常的热烈,而常见的方式是以下几种:

  • Inline CSS
  • CSS In JS
  • Styled Components
  • CSS Modules

不过每种方式都有自己的利弊,也各有争议。接下来我们先不好坏,分别来体验一下这几种方式写CSS的不同之处。

在开始之前,先使用 Create React APP 来构建React的项目,用来验证React项目中编写CSS的不同之处。

╰─➤  npx create-react-app react-styling
╰─➤  cd react-styling
╰─➤  npm run start

React在没有任何其他工具的情况之下,仅支持两种处理样式的方式: style 道具( props )与 <style> 标签和CSS样式表。 style 道具使用JavaScript对象(CSS属性和值),并最终将其转换为元素的内联样式,如下所示:

// JSX
<p style={{backgroundColor: 'red'}}>Hello, {props.name}</p>

qQv67ry.png!web

还可以这样写:

// App Components
// JSX
<p style={{ backgroundColor: props.color }}>Hello, {props.name}</p>

// index.js
import App from './App';
ReactDOM.render(<App name="大漠" color="#306"/>, document.getElementById('root'));

reAjQfB.png!web

第一种是和我们平时在DOM中的元素上使用 style 属性设置行内样式是一样的;第二种是使用 props 的给 style 设置样式,编译出来也是行内样式。这两种方式输出来的样式都是行内样式,如果从选择器权重来说,它的权重是非常高的,在调用组件,要覆盖其样式就不容易了。

我们还可以在一个样式表文件中设置样式,比如在 App.css 文件中:

.App {
    text-align: center;
}

.App-logo {
    animation: App-logo-spin infinite 20s linear;
    height: 40vmin;
    pointer-events: none;
}

App 组件中可以通过 className 来调用 App.css 中的类名:

// App.js
import './App.css';

function App(props) {
    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p style={{ backgroundColor: props.color }}>Hello, {props.name}</p>
            </header>
        </div>
    );
}

编译出来之后如下图所示:

Ez6JJnj.png!web

这是React中编写CSS最基本的方式。这两种基本方式和我们在普通的Web中编写CSS方式是一样的。众所周知,Web中编写CSS是较为痛苦的,因为类名的冲突,全局的污染等等。所以社区才会借助一些工具的方式来改变编写CSS。

Vue的体系下有 scoped 和CSS Modules ;在React中编写的方式就更多,即接下来要介绍的这些方式。

Inline CSS

Inline CSS称为内联CSS,即在HTML标签元素中使用 style 属性( Attribute )来定义CSS属性,常被称为 行内样式 。如下面这样:

<p style="font-size: 20px; color:#4a54f1; text-align:center; padding-top:100px;">
    Hello World!!!
</p>

而在Web中,我们一直提倡的是结构和样式分离,所以一直不推荐行内样式这样的写法。而如今天在React框架体系中,又开始提 Inline CSS ,那么是不是有点倒退了的意思呢?该话题先不讨论,这里咱们只来聊聊Inline CSS在React中的使用,并且该使用是否适合我们的开发习惯。

在React开发中,我们一般使用JSX编写。JSX将被转换为 React.createElement(...) ,所有的属性都将成为 props 对象的一部分。

有关于JSX的详细介绍,可以阅读《深入了解JSX》一文。

在React中,内联样式不指定为 字符串style 属性接受带有驼峰格式的JavaScript对象。例如:

margin-top       ─➤ marginTop
border-radius    ─➤ borderRadius
font-weight      ─➤ fontWeight
background-color ─➤ backgroundColor

下面是React中定义内联CSS的基本步骤:

  • 将CSS属性名称用驼峰的格式编写,比如 font-size 要写成 fontSize
  • 创建一个对象,将所有CSS属性作为 key ,CSS属性的值作为 value
  • 将该对象分配给 style 属性

我们来尝试着将上面的HTML代码,看看在React中怎么来实现:

// App.js
import React from 'react';

function App() {
    const styleObj = {
        fontSize: '20px',
        color: '#4a54f1',
        textAlign: 'center',
        paddingTop: '100px'
    }
    return (
        <p style={ styleObj }>Hello World!!!</p>
    );
}

export default App;

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

你将看到的效果如下:

2QJrIfJ.png!web

上面的写法和JSX中在 style 中引入需要的样式得到的结果是一样的


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK