自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你了解 JSX,那你了解 StyleX 么?

開發(fā) 前端
從Meta內部使用,到大會對外宣傳,這期間肯定已經經歷大量內部項目的洗禮。而從做完宣傳到最終開源,又經歷了快5年時間。那么,這款Meta出品、打磨這么長時間的「CSS-in-JS庫」,到底有什么特點呢?本文讓我們來聊聊。

大家好,我卡頌。

近日,Meta開源了一款「CSS-in-JS庫」 —— StyleX??疵绞?,Style - X是不是有點像JS - X,他們有關系么?當然有。

JSX是一種「用JS描述HTML」的語法規(guī)范,廣泛應用于前端框架中(比如React、SolidJS...),由Meta公司提出。

同樣的,按照Meta的設想,StyleX是一種「用JS描述CSS」的語法規(guī)范。

早在React Conf 2019[1],Meta工程師「Frank」就介紹了這種Meta內部使用的「CSS-in-JS庫」。

從Meta內部使用,到大會對外宣傳,這期間肯定已經經歷大量內部項目的洗禮。而從做完宣傳到最終開源,又經歷了快5年時間。

那么,這款Meta出品、打磨這么長時間的「CSS-in-JS庫」,到底有什么特點呢?

本文讓我們來聊聊。

為什么需要CSS解決方案

市面上有非常多「CSS解決方案」,比如:

  • BEM命名規(guī)范
  • CSS Module規(guī)范
  • 原子CSS(比如TailwindCSS)
  • CSS-in-JS(比如emotion)

為什么需要這些方案?原生CSS哪里不好?在這里,我們舉個小例子(例子來源于「React Conf 2019」)??紤]如下代碼:

CSS文件如下:

.blue {color: blue;}
.red {color: red;}

HTML文件如下:

<p class="red blue">我是什么顏色?</p>

請問p標簽是什么顏色的?

從class來看,blue在red后面,p應該是藍色的么?

實際上,樣式取決于他們在樣式表中定義的順序,.red的定義在.blue后面,所以p應該是紅色的。

是不是已經有點暈了?再增加點難度。如果.red和.blue分別在兩個文件中定義呢?

# css文件1
.blue {color: blue;}
# css文件2
.red {color: red;}

那p的樣式就取決于最終打包代碼中樣式文件的加載順序。

上面只是原生CSS中「選擇器優(yōu)先級相關的一個缺陷」(除此外還有其他缺陷,比如「作用域缺失」...)。隨著項目體積增大、項目維護時間變長、項目維護人員更迭,這些缺陷會被逐漸放大。

正是由于這些原因,才出現了各種「CSS解決方案」。

StyleX的基本使用

StyleX的API很少,掌握下面兩個就能上手使用:

  • stylex.create,創(chuàng)建樣式。
  • stylex.props,定義props。

比如:

import * as stylex from 'stylex';

// 創(chuàng)建樣式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定義props
const redStyleProps = stylex.props(styles.red);

使用時:

<div {...redStyleProps}>文字顏色是紅色</div>

stylex是如何解決上面提到的red blue優(yōu)先級問題呢?其實很簡單,考慮如下代碼:

import * as stylex from 'stylex';

// 創(chuàng)建樣式
const styles = stylex.create({
  red: {color: 'red'},
  blue: {color: 'blue'}
});

// 使用
<p {...styles.props(styles.red, styles.blue)}></p>

樣式的優(yōu)先級只需要考慮styles.props中的定義順序(blue在red后面,所以顏色為blue),不需要考慮樣式表的存在。

有些同學會說,看起來和常見的CSS-in-JS沒啥區(qū)別啊。那stylex相比于他們的優(yōu)勢是啥呢?

相比其他CSS-in-JS的優(yōu)勢

首先要明確,stylex雖然以CSS-in-JS的形式存在,但本質上他是一種「用JS描述CSS的規(guī)范」。文章開頭也提到,他的定位類似JSX。

既然是規(guī)范,那他就不是對CSS的簡單封裝、增強,而是一套「自定義的樣式編寫規(guī)范」,只不過這套規(guī)范最終會被編譯為CSS。

作為對比,Less、Sass這樣的「CSS預處理器」就是對CSS語法的封裝、增強

那么,stylex都有哪些規(guī)范呢?

比如,stylex鼓勵將樣式與組件寫在同一個文件,類似Vue的SFC(單文件組件)。這么做除了讓組件的樣式與邏輯更方便維護,也減少了stylex編譯的實現難度。

再比如,CSS中各種選擇器的復雜組合增強了選擇器的靈活性。但同時也增強了不確定性。舉個例子,考慮如下三個選擇器:

  • .className > *
  • .className ~ *
  • .className:hover > div:first-child

這些對.className應用的選擇器將影響.className的某些后代。當這樣的選擇器多了后,很可能會在開發(fā)者不知道的情況下改變某些后代元素的樣式。

遇到這種情況我們一般會怎么處理呢?正確的選擇當然是找到上述影響后代的選擇器,再修改他。

但大家工作都這么忙,遇到這種問題,多半就是用新的選擇器覆寫樣式,必要的時候還會加!important后綴。久而久之,這代碼就沒法維護了。

為了規(guī)避這種情況,在stylex中,除了「可繼承樣式」(指「當父元素應用后,子孫元素默認會繼承的樣式」,比如color)外,不支持這些「可以改變子孫后代樣式的選擇器」。

那我該如何讓子孫組件獲得父組件同樣的樣式呢?通過props透傳啊~

也就是說,stylex禁用了CSS中可能造成混淆的選擇器,用JS的靈活性彌補這部分功能的缺失。

有些同學可能會說:這些功能,其他「CSS-in-JS庫」也能做啊。

這就要談到「CSS-in-JS庫」最大的劣勢 —— 為了計算出最終樣式,在運行時會造成額外的樣式計算開銷。

stylex通過編譯來減少運行時的開銷。比如對于上面提到過的stylex的代碼:

import * as stylex from 'stylex';

// 創(chuàng)建樣式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定義props
const redStyleProps = stylex.props(styles.red);

編譯后的產物包括如下兩部分:

JS的編譯產物:

import * as stylex from 'stylex';
const redStyleProps = {className: 'x1e2nbdu'};

CSS的編譯產物:

.x1e2nbdu {
  color: red;
}

所以,運行時實際運行的代碼始終為:

<div {...{className: 'x1e2nbdu'}}>...</div>

對于再復雜的樣式,stylex都會通過編譯生成「可復用的原子類名」。

即使是跨文件使用樣式,比如我們在另一個文件也定義個使用color: 'red'樣式的stylex屬性foo:

import * as stylex from '@stylexjs/stylex';

const styles = stylex.create({
  foo: {
    color: 'red',
  },
  bar: {
    backgroundColor: 'blue',
  },
});

會得到如下編譯結果,其中x1e2nbdu是一個原子類名,他是上一個文件中styles.red的編譯產物:

import * as stylex from '@stylexjs/stylex';

const styles = {
  foo: {
    color: 'x1e2nbdu',
    $$css: true,
  },
  bar: {
    backgroundColor: 'x1t391ir',
    $$css: true,
  },
};

隨著項目體積增大,樣式表的體積也能控制在合理的范圍內。這種對原子類名的控制粒度是其他「CSS-in-JS庫」辦不到的。

相比于原子CSS的優(yōu)勢

stylex相比TailwindCSS這樣的原子CSS有什么優(yōu)勢呢?

這就要談到原子CSS的一個特點 —— 使用約定好的字符串實現樣式。比如,使用TailwindCSS定義圖片的樣式:

<img class="w-24 h-24 rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">

效果如下:

由于樣式都是由不同的「原子類名字符串」組合而成,TS沒法分析,這就沒法實現「樣式的類型安全」。

什么叫「樣式的類型安全」?通俗的講,如果我實現一個組件,組件通過style props定義樣式,我只希望使用者能夠改變color與fontSize兩個樣式屬性,不能修改其他屬性。如果能實現這一點,就是「樣式的類型安全」。

「樣式的類型安全」有什么意義呢?舉個例子:設想開發(fā)基礎組件庫的團隊使用stylex。那么當業(yè)務團隊使用該組件庫時,就只能自定義組件的一些樣式(由組件庫團隊約束)。

當基礎組件庫升級時,組件庫團隊能很好對組件樣式向下兼容(因為知道只有哪些樣式允許被修改)。

在stylex中,由于stylex.create的產物本質是對象,所以我們可以為每個產物定義類型聲明。比如在如下代碼中,我們限制了組件style props只能接受如下stylex樣式:

import type {StyleXStyles} from '@stylexjs/stylex';

type Props = {
  // ...
  style?: StyleXStyles<{
    color?: string;
    backgroundColor?: string;
    borderColor?: string;
    borderTopColor?: string;
    borderEndColor?: string;
    borderBottomColor?: string;
    borderStartColor?: string;
  }>;
};

總結

我猜想,當更多人知道stylex后,他會收到比當初TailwindCSS火時更多的兩級分化的評價。

畢竟,stylex的設計初衷是為了解決Meta內部復雜應用的樣式管理。如果:

  • 你項目沒有達到Meta這樣的體量
  • 你項目沒有多年的迭代周期
  • 你項目前前后后沒有多個工程師經手

那大概率是不能接受stylex設計理念中的這些約束。

對于stylex,你怎么看?

參考資料

[1]React Conf 2019:https://www.youtube.com/watch?v=9JZHodNR184&t=270s。

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2016-09-26 14:45:46

微服務

2009-12-17 11:28:03

Linux系統(tǒng)開機

2011-08-08 15:14:11

PPPOE

2019-10-23 11:24:44

LinuxLinux目錄Linux系統(tǒng)

2023-09-19 07:19:46

2009-12-17 14:56:32

Linux程序設計

2022-01-05 21:54:51

網絡分層系統(tǒng)

2019-12-10 10:13:58

HTTPNginxRedirect

2021-11-02 11:35:17

通信進程面試

2019-12-18 15:11:42

數組集合數據

2024-01-29 07:43:42

Java獨占鎖共享鎖

2009-12-24 16:51:54

Linux hosts

2018-06-29 08:36:50

2021-01-13 07:34:31

Tomcat流程接口

2022-05-06 16:31:27

人工智能自然語言生物特征識別

2020-04-02 07:55:07

分析方法論研發(fā)

2018-10-07 06:30:40

代碼設計模式面向對象原則

2022-05-05 21:06:33

人工智能計算機視覺自然語言處理

2020-03-25 08:47:22

智能邊緣邊緣計算網絡

2021-07-02 21:07:35

負載均衡模型nginx
點贊
收藏

51CTO技術棧公眾號