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文件寫法基本一致
相關文章
相關標籤/搜索