React系列 --- 从使用React了解Css的各类使用方案(六)

To define is to limit.
定义同样东西,就意味着限制了它。

——王尔德 《道林·格雷的画像》css

React系列

React系列 --- 简单模拟语法(一)
React系列 --- Jsx, 合成事件与Refs(二)
React系列 --- virtualdom diff算法实现分析(三)
React系列 --- 从Mixin到HOC再到HOOKS(四)
React系列 --- createElement, ReactElement与Component部分源码解析(五)
React系列 --- 从使用React了解Css的各类使用方案(六)
React系列 --- 从零构建状态管理及Redux源码解析(七)
React系列 --- 扩展状态管理功能及Redux源码解析(八)html

前言

这里主要总结一下CSS是怎么一步步演化呈如今百花齐放的局面,从用上React以后就更加多选择了,我就举例一下个人理解和用过的方案,还有一些了解过以为还不错的方案.自己没有推荐或贬低哪些的意思,只是以为能够知足需求的都是可使用的方案.前端

CSS

用官方口吻来讲就是react

CSS 可以对网页中元素位置的排版进行像素级精确控制,支持几乎全部的字体字号样式,拥有对网页对象和模型样式编辑的能力。

具备如下特色:webpack

  1. 丰富的样式定义

    CSS提供了丰富的包括但不限于样式外观,文本字体,背景属性,边距形状等等的能力,还有一些浏览器特有的属性定制.css3

  2. 易于使用修改

    能够将样式定义在HTML元素的style属性中,HTML文档的header部分,也能够将样式声明在一个专门的CSS文件中。git

    能够将相一样式的元素进行归类使用同一个样式进行定义,也能够将某个样式应用到全部同名的HTML标签中。github

  3. 多页面应用

    CSS样式表理论上不属于任何页面文件,在任何页面文件中均可以将其引用。这样就能够实现多个页面风格的统一。web

  4. 层叠

    简单的说,层叠就是对一个元素屡次设置同一个样式,后来定义的样式将对前面的样式设置进行重写。算法

  5. 体积减小

    在使用HTML定义页面效果的网站中,每每须要大量或重复的表格和font元素造成各类规格的文字样式,而将样式的声明单独放到CSS样式表中,能够大大的减少页面的体积,这样在加载页面时使用的时间也会大大的减小。另外,CSS样式表的复用更大程序的缩减了页面的体积,减小下载的时间。

而后随着用户审美水平日益提升的标准和需求,普通的样式已经不足以支撑起来了,特别有些简单要求还会让开发绞尽脑汁用尽各类奇淫巧技来实现,这种状况甚至会大大违背结构和样式分离的原则.

CSS3

做为CSS的升级版,主要包括盒子模型、列表模块、超连接方式、语言模块、背景和边框、文字特效、多栏布局等模块.

CSS3规范的一个新特色是被分为若干个相互独立的模块。一方面分红若干较小的模块较利于规范及时更新和发布,及时调整模块的内容,这些模块独立实现和发布,也为往后CSS的扩展奠基了基础。另一方面,因为受支持设备和浏览器厂商的限制,没备或者厂商能够有选择的支持一部分模块,支持CSS3的一个子集,这样有利于CSS3的推广,但不一样浏览器在不一样时段支持不一样特性,这也让跨浏览器开发变得复杂,固然截止到2019,主流浏览器已经基本支持了.低端版本也能经过各类辅助插件完成.

提高优点:

  1. 减小开发成本与维护成本

    例如之前须要使用图片定位模拟圆角,绝对定位+定时器模拟动画,元素伪造滚动条样式等各类繁琐工做均可以省略掉了.

  2. 提升页面性能

    减小多余的标签嵌套以及图片的使用数量,意味着用户要下载的内容将会更少,页面加载也会更快,可以减小用户访问Web站点时的HTTP请求数,这是提高页面加载速度的最佳方法之一

CSS3的推广一方面加强了样式的展现,一方面免去开发实现的额外工程,可是本质上并无减小开发的工做量,由于有不少相似而不相同的样式仍是须要手写出来.如今的网页愈来愈大,画面愈来愈丰富,因而就应运而生出了------

预处理器

由于我都是使用SCSS,就以此举例,可是其实语法和实现功能大体相同的.

预处理器是一种强化 CSS 的辅助工具,它在 CSS 语法的基础上增长了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更增强大与优雅,有助于更好地组织管理样式文件,以及更高效地开发项目.

简单举例经常使用而强大的特性:

  1. 嵌套规则 (Nested Rules)

    容许将一套 CSS 样式嵌套进另外一套样式中,内层的样式将它外层的选择器做为父选择器,还有属性嵌套,占位符选择器等等

  2. SassScript

    能够经过声明变量,函数,运算等抽取重复样式代码减小大量重复样板代码.

  3. 指令

    @import导入 SCSS 或 Sass 文件 ,@media 嵌套在 CSS 规则内,@extend继承样式等

  4. 控制指令

    运用各类判断循环实现控制样式

CSS的瓶颈

上面都是前端开发的标配技能,懂得天然都懂,就不说太多了,可是该碰到的坑天然都会遇到.

主要这么几个:

  1. 全局污染

    好的规范天然可以极大方便重用样式减小代码,可是别说多人协做开发,即便我的维护均可能碰到多种样式覆盖,权重优先级混乱,冗余重复属性过多,因而各类内联样式,!important强制最早等写法,虽然也有其余方案如功能属性class拆分避免这种窘境,可是增大开发的参与难度,很难造成一套适用标准,起码我以为太繁琐了.

  2. 命名烦恼

    元素嵌套越深,若是想命名语义化明确点就可能致使愈来愈长越复杂的命中规则,而有一些一次性的样式也不得不遵循这种规则,不然用内联样式替代

  3. 样式压缩

    由于样式对应到具体的引用属性id,class,选择器等,这一块是没办法省略的,嵌套越深刻选择器前缀可能就越长,例如#A .B .C .D p{}这种

预处理器只是简化开发写法,实际编译完成也就这个样,本质上的问题没有获得解决.

CSS-in-JS

React自己没有定义样式的主张,而是用第三方库提供的CSS-in-JS.这里是一些实现的对比,之因此会出现种类繁多的第三方库是由于它们实现功能的支持有所区别,主要在

  1. Automatic Vendor Prefixing (自动添加前缀)
  2. Pseudo Classes (伪类)
  3. Media Queries (媒体查询)
  4. Styles As Object Literals (对象字面量样式)
  5. Extract CSS File (提取CSS文件)

例如React的官方示例原生style属性使用

style 属性接受具备驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串。 这与 JavaScript DOM 的  style 属性一致,可是更高效,而且防止XSS安全漏洞。 例如:
const divStyle = {
  color: 'blue',
  backgroundImage: 'url(' + imgUrl + ')',
};

function HelloWorldComponent() {
  return <div style={divStyle}>Hello World!</div>;
}

注意:

  1. 样式不自动进行兼容。 要支持旧版本的浏览器,您须要提供相应的样式属性
  2. React 会自动为某些内联样式的数字属性值附加一个 “px” 后缀。 若是你想使用 “px” 之外的单位,请明确指定单位,并将该值指定为字符串
  3. 并不支持全部的 css,例如媒体查询,:before:nth-child等 pseudo selectors

而后咱们也能用一些其余的CSS-in-JS库解决,我就拿比较多人使用支持功能比较完善的来举例一下,下面方案都属于这种,可是倾向和用法上有必定区别:

aphrodite

Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation.

Support for colocating your styles with your JavaScript component.

支持功能

  • 不强制和React搭配才能使用
  • 支持媒体查询无需window.matchMedia
  • 支持伪选择器像:hover, :active等等,不须要在组件中存储悬停或活动状态。 :visited也能良好支持
  • 支持自动全局@font-face检测和插入
  • 在指定多个样式时,尊重优先顺序
  • 不须要AST转换
  • 只向DOM中注入渲染所需的确切样式。
  • 能够用于服务器渲染
  • 低依赖,小(20k,压缩后6k)
  • 没有外部的Css文件生成
  • 自动添加前缀

示例

import React, { Component } from 'react';
import { StyleSheet, css } from 'aphrodite';

class App extends Component {
    render() {
        return <div>
            <span className={css(styles.red)}>
                This is red.
            </span>
            <span className={css(styles.hover)}>
                This turns red on hover.
            </span>
            <span className={css(styles.small)}>
                This turns red when the browser is less than 600px width.
            </span>
            <span className={css(styles.red, styles.blue)}>
                This is blue.
            </span>
            <span className={css(styles.blue, styles.small)}>
                This is blue and turns red when the browser is less than
                600px width.
            </span>
        </div>;
    }
}

const styles = StyleSheet.create({
    red: {
        backgroundColor: 'red'
    },

    blue: {
        backgroundColor: 'blue'
    },

    hover: {
        ':hover': {
            backgroundColor: 'red'
        }
    },

    small: {
        '@media (max-width: 600px)': {
            backgroundColor: 'red',
        }
    }
});

固然也不少人不太接受这种方式书写Css,还把html结构嵌套一堆className={css()}的写法.

styled-components

使用标记的模板文本和CSS的强大功能,样式组件容许您编写实际的CSS代码来样式化组件。它还删除了组件和样式之间的映射——将组件用做低级样式结构再简单不过了!

风格组件既兼容React(用于web),也兼容React Native——这意味着它甚至是真正通用的应用程序的完美选择!

示例

import React from 'react';

import styled from 'styled-components';

// Create a <Title> react component that renders an <h1> which is
// centered, palevioletred and sized at 1.5em
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

// Create a <Wrapper> react component that renders a <section> with
// some padding and a papayawhip background
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use them like any other React component – except they're styled!
<Wrapper>
  <Title>Hello World, this is my first styled component!</Title>
</Wrapper>

优势

  • 直接将样式组件化,移除样式和组件的映射关系
  • 支持组件继承,方便复用
  • 和原有CSS方式无障碍搭配使用

styled-jsx

这是我查资料的时候了解到的一种方案,由于没有实际用过,因此我只贴上它的功能示例

主要功能

  • 彻底的CSS支持, no tradeoffs in power
  • 运行时大小仅为3kb(从12kb压缩为gzip)
  • 彻底隔离:选择器、动画、关键帧
  • 内置CSS浏览器前缀
  • 很是快速、最小和高效
  • 非服务器渲染时高效运行注入
  • 面向将来:至关于服务器可渲染的"Shadow CSS"
  • 支持源映射
  • 支持动态样式和主题
  • 经过插件进行CSS预处理

示例

export default () => (
  <div>
    <p>only this paragraph will get the style :)</p>

    { /* you can include <Component />s here that include
         other <p>s that don't get unexpected styles! */ }

    <style jsx>{`
      p {
        color: red;
      }
    `}</style>
  </div>
)

CSS Module

这是我在学习webpack的Css-loader的时候了解到的一种方案,如今在使用的方案

CSS Module是一个CSS文件,默认全部类和动画命名都限于局部范围.全部资源(url(...))@imports都在模块请求格式.

Css模块会被编译成底层交换格式像ICSS或者Interoperable CSS,可是书写格式和普通CSS文件同样.

当从JS模块导入CSS模块时,它导出一个具备从本地名称到全局名称的全部映射的对象。

CSS

/* style.css */
.className {
  color: green;
}

JSX

import { PureComponent } from 'react';
import styles from './index.scss';

class Page2 extends PureComponent {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div className={styles.className}>
      </div>
    );
  }
}

固然这不是只限于React,使用webpack或者其余打包工具的方式都能支持使用.

优势

模块化和可重用性

  • 没有冲突
  • 显性依赖
  • 不会污染全局
  • 能够配合预处理器使用
  • API少,开发单独CSS文件写法基本一致
相关文章
相关标签/搜索