CSS in JS 簡介

yeyun0995 7年前發布 | 14K 次閱讀 CSS 前端技術 JavaScript

1、以前,網頁開發有一個原則,叫做 "關注點分離" (separation of concerns)。

它的意思是,各種技術只負責自己的領域,不要混合在一起,形成耦合。對于網頁開發來說,主要是三種技術分離。

  • HTML 語言:負責網頁的結構,又稱語義層
  • CSS 語言:負責網頁的樣式,又稱視覺層
  • JavaScript 語言:負責網頁的邏輯和交互,又稱邏輯層或交互層

簡單說,就是一句話,不要寫"行內樣式"(inline style)和"行內腳本"(inline script)。比如,下面代碼就很糟糕(查看 完整代碼 )。

<h1 style="color:red;font-size:46px;"  onclick="alert('Hi')">
  Hello World
</h1>

2、React 出現以后,這個原則不再適用了。因為,React 是組件結構,強制要求把 HTML、CSS、JavaScript 寫在一起。

上面的例子使用 React 改寫如下(查看 完整代碼 )。

const style = {
  'color': 'red',
  'fontSize': '46px'
};

const clickHandler = () => alert('hi'); 

ReactDOM.render(
  <h1 style={style} onclick={clickHandler}>
     Hello, world!
  </h1>,
  document.getElementById('example')
);

上面代碼在一個文件里面,封裝了結構、樣式和邏輯,完全違背了"關注點分離"的原則,很多人不適應。

但是,這有利于組件的隔離。每個組件包含了所有需要用到的代碼,不依賴外部,組件之間沒有耦合,很方便復用。所以,隨著 React 的走紅和組件模式深入人心,這種"關注點混合"的新寫法逐漸成為主流。

3、表面上,React 的寫法是 HTML、CSS、JavaScript 混合在一起。但是,實際上不是。現在其實是用 JavaScript 在寫 HTML 和 CSS。

React 在 JavaScript 里面實現了對 HTML 和 CSS 的封裝,我們通過封裝去操作 HTML 和 CSS。也就是說,網頁的結構和樣式都通過 JavaScript 操作。

4、React 對 HTML 的封裝是 JSX 語言 ,這個在各種 React 教程都有詳細介紹,本文不再涉及了,下面來看 React 對 CSS 的封裝。

React 對 CSS 封裝非常簡單,就是沿用了 DOM 的 style 屬性對象 ,這個在前面已經看到過了。

const style = {
  'color': 'red',
  'fontSize': '46px'
};

上面代碼中,CSS 的 font-size 屬性要寫成 fontSize ,這是 JavaScript 操作 CSS 屬性的 約定 。

由于 CSS 的封裝非常弱,導致了一系列的第三方庫,用來加強 React 的 CSS 操作。它們統稱為 CSS in JS,意思就是使用 JS 語言寫 CSS。根據不完全統計,各種 CSS in JS 的庫至少有 47種 。老實說,現在也看不出來,哪一個庫會變成主流。

你可能會問,它們與"CSS 預處理器"(比如 Less 和Sass,包括 PostCSS)有什么區別?回答是 CSS in JS 使用 JavaScript 的語法,是 JavaScript 腳本的一部分,不用從頭學習一套專用的 API,也不會多一道編譯步驟。

5、上周,我看到一個新的 CSS in JS 庫,叫做 polished.js 。它將一些常用的 CSS 屬性封裝成函數,用起來非常方便,充分體現使用 JavaScript 語言寫 CSS 的優勢。

我覺得這個庫很值得推薦,這篇文章的主要目的,就是想從這個庫來看怎么使用 CSS in JS。

首先,加載 polished.js。

const polished = require('polished');

如果是瀏覽器,插入下面的腳本。

<script src="https://unpkg.com/polished@1.0.0/dist/polished.min.js">
</script>

polished.js 目前有50多個方法,比如 clearfix 方法用來清理浮動。

const styles = {
  ...polished.clearFix(),
};

上面代碼中, clearFix 就是一個普通的 JavaScript 函數,返回一個對象。

polished.clearFix()
// {
//  &::after: {
//    clear: "both",
//    content: "",
//    display: "table"
//  }
// }

"展開運算符"( ... )將 clearFix 返回的對象展開,便于與其他 CSS 屬性混合。然后,將樣式對象賦給 React 組件的 style 屬性,這個組件就能清理浮動了。

ReactDOM.render(
  <h1 style={style}>Hello, React!</h1>,
  document.getElementById('example')
);

從這個例子,大家應該能夠體會 polished.js 的用法。

6、

下面再看幾個很有用的函數。

ellipsis 將超過指定長度的文本,使用省略號替代(查看 完整代碼 )。

const styles = {
  ...polished.ellipsis('200px')
}

// 返回值
// {
//   'display': 'inline-block',
//   'max-width': '250px',
//   'overflow': 'hidden',
//   'text-overflow': 'ellipsis',
//   'white-space': 'nowrap',
//   'word-wrap': 'normal'
// }

hideText 用于隱藏文本,顯示圖片。

const styles = {
  'background-image': 'url(logo.png)',
  ...polished.hideText(),
};

// 返回值
// {
  'background-image': 'url(logo.png)',
  'text-indent': '101%',
  'overflow': 'hidden',
  'white-space': 'nowrap',
}

hiDPI 指定高分屏樣式。

const styles = {
 [polished.hiDPI(1.5)]: {
   width: '200px',
 }
};

// 返回值
//'@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
// only screen and (min--moz-device-pixel-ratio: 1.5),
// only screen and (-o-min-device-pixel-ratio: 1.5/1),
// only screen and (min-resolution: 144dpi),
// only screen and (min-resolution: 1.5dppx)': {
//  'width': '200px',
//}

retinaImage 為高分屏和低分屏設置不同的背景圖。

const styles = {
 ...polished.retinaImage('my-img')
};

// 返回值
//   backgroundImage: 'url(my-img.png)',
//  '@media only screen and (-webkit-min-device-pixel-ratio: 1.3),
//   only screen and (min--moz-device-pixel-ratio: 1.3),
//   only screen and (-o-min-device-pixel-ratio: 1.3/1),
//   only screen and (min-resolution: 144dpi),
//   only screen and (min-resolution: 1.5dppx)': {
//    backgroundImage: 'url(my-img_2x.png)',
//  }

7、polished.js 提供的其他方法如下 。

  • normalize() :樣式表初始化
  • placeholder() :對 placeholder 偽元素設置樣式
  • selection() :對 selection 偽元素設置樣式
  • darken() :調節顏色深淺
  • lighten() :調節顏色深淺
  • desaturate() :降低顏色的飽和度
  • saturate() :增加顏色的飽和度
  • opacify() :調節透明度
  • complement() :返回互補色
  • grayscale() :將一個顏色轉為灰度
  • rgb() :指定紅、綠、藍三個值,返回一個顏色
  • rgba() :指定紅、綠、藍和透明度四個值,返回一個顏色
  • hsl() :指定色調、飽和度和亮度三個值,返回一個顏色
  • hsla() :指定色調、飽和度、亮度和透明度三個值,返回一個顏色
  • mix() :混合兩種顏色
  • em() :將像素轉為 em
  • rem() :將像素轉為 rem

目前, polished.js 只是1.0版,以后應該會有越來越多的方法。

8、polished.js 還有一個特色:所有函數默認都是柯里化的,因此可以進行函數組合運算,定制出自己想要的函數。

import { compose } from 'ramda';
import { lighten, desaturate } from 'polished';

const tone = compose(lighten(10), desaturate(10))

上面代碼使用 Ramda 函數庫完成組合運算。Ramda 的用法可以參考我寫的教程。

 

 

來自:http://www.ruanyifeng.com/blog/2017/04/css_in_js.html

 

 本文由用戶 yeyun0995 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!