每年十月,最大的國際 React 會議都會在印度果阿舉行。是的,我說的是 React India。今年(2024 年)對我來說更加特別,因為我有機會在這場盛大的會議上發言。如果你錯過了現場觀看的話,這是我的演講錄音。如果您喜歡閱讀而不是觀看視頻,那麼這個部落格非常適合您!讓我們深入探討一下。
StyleX 是 Meta 的新的、可擴展的樣式庫,現在被用作 Facebook、Instagram 和 WhatsApp 等平台背後的主要係統。它解決了 CSS-in-JS 方法所遇到的痛點,特別是在大規模 React 應用程式中。透過提供融合原子 CSS 和靜態 CSS 最佳功能的混合解決方案,StyleX 提供了高效、模組化和可擴展的替代方案。
原子 CSS 生成:StyleX 採用原子 CSS 生成,這表示它為每個樣式規則建立小型、可重複使用的類別。這種方法不僅可以最大限度地減少最終 CSS 套件中的冗餘,還可以透過減少樣式表的整體大小來提高效能。
CSS 重複資料刪除:透過為每個樣式產生唯一的類別標識符,StyleX 有效地消除了重複的樣式。此重複資料刪除程序可確保每個屬性值對僅渲染一次,進一步有助於實現更精簡的 CSS 輸出。
「最後應用的樣式總是獲勝!」:StyleX 遵循可預測的樣式規則,其中最後應用的樣式優先。此功能簡化了調試並增強了開發人員的信心,因為它減輕了對樣式規則衝突的擔憂。
針對 React 進行了最佳化:StyleX 專為 React 應用程式設計,無縫整合到 React 生態系統中。它允許開發人員直接在其元件中定義樣式,從而形成更具凝聚力的開發工作流程。
Flow 和 TypeScript 支援:StyleX 是用「Flow」(由 Meta 創建)編寫的,它還為 TypeScript 提供強大的支持,為樣式和主題啟用類型安全的 API。這種類型安全性增強了程式碼的可靠性和可維護性,使管理複雜的樣式場景變得更加容易。
靈活的條件樣式:使用 StyleX,開發人員可以依照元件狀態或 props 有條件地套用樣式。這種靈活性允許動態樣式適應使用者互動或應用程式狀態的變化。
範圍樣式:StyleX 的範圍樣式功能可確保樣式僅套用於其預期的元件。這可以防止大型程式碼庫中經常出現的意外副作用和特異性問題。
更少的運行時計算:StyleX 通過在編譯時將所有樣式捆綁到靜態 CSS 文件中來最大限度地減少運行時計算。這種優化可以縮短渲染時間並提高效能,尤其是在大型應用程式中。
更好的程式碼可維護性:透過將樣式與其各自的組件共置並利用原子類,StyleX 提高了程式碼的可維護性。開發人員可以輕鬆理解和修改樣式,而無需篩選大量樣式表。
最小 CSS 輸出:使用原子 CSS 會導致最小 CSS 輸出,這對效能特別有利。隨著專案規模和複雜性的增加,StyleX 可確保 CSS 捆綁包在不犧牲功能的情況下保持可管理性。
適用於各種規模的項目:雖然 StyleX 適用於各種規模的項目,但它在大型應用程式中確實表現出色。其架構旨在處理廣泛的樣式需求的複雜性,而不影響效能或可維護性。
本文中的程式碼範例是用 React 寫的,我們將主要使用兩個元件:App.jsx 和 Button.jsx。在新增樣式之前,我們先來看看這些元件的基本結構。
import Button from "./components/Button"; const App = () => { return ( <div> <h1>StyleX by Meta</h1> <Button text="Get Started" /> </div> ); }; export default App;
// Button.jsx import PropTypes from "prop-types"; const Button = ({ text }) => { return <button>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: "black", color: "white", }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
要使用這些樣式,我們需要從 styleX 套件中匯入它們,然後使用以物件作為參數的 stylex.create 方法定義樣式。然後我們可以使用 stylex.props 方法將樣式套用到元件。
在此範例中,base 是我們要套用的樣式的名稱。我們在 StyleX 中稱它們為 命名空間。這就是我們的按鈕組件現在的樣子。
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: { default: "black", ":hover": "blue", }, color: "white", }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
使用 StyleX,為偽類添加樣式非常簡單。在前面的範例中,backgroundColor 是一個字串。在這裡,我們將其轉換為具有預設值和偽類別的物件。
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: { default: "black", ":hover": "blue", }, color: "white", width: { default: "100px", "@media (max-width: 476px)": "100%", }, }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
與其他樣式庫相比,我們在 StyleX 中做的不同的一件事是媒體查詢。在這裡,我們根據需求將媒體查詢應用於每個命名空間。在此範例中,我們將較大螢幕的按鈕寬度定義為 100px,較小螢幕或行動裝置的按鈕寬度定義為 100%。
讓我們擴展前面的範例,看看如何建立此按鈕的不同變體。
const styles = stylex.create({ base: { fontSize: 18, backgroundColor: { default: "teal", ":hover": "blue", }, color: "white", width: { default: "100px", "@media (max-width: 476px)": "100%", }, }, highlighted: { backgroundColor: "orange", }, danger: { backgroundColor: "red", }, primary: { backgroundColor: "green", }, }); const Button = ({ text, isHighlighted, variant }) => { return ( <button {...stylex.props( styles.base, isHighlighted && styles.highlighted, // conditional styling styles[variant] )} > {text} </button> ); }; Button.propTypes = { text: PropTypes.string.isRequired, isHighlighted: PropTypes.bool, variant: PropTypes.oneOf(["danger", "primary"]), };
讓我們為 stylex.create 方法添加更多命名空間,並為它們提供不同的背景顏色。此外,我們在 Button 元件中接受了 2 個新的 props。 isHighlighted 是一個布林屬性,我們用它來套用突出顯示的命名空間。變數是我們用來應用主要、危險或突出顯示的命名空間的道具。
// App.jsx import Button from "./components/Button"; const App = () => { return ( <div> <h1>StyleX by Meta</h1> <div {...stylex.props(styles.main)}> <Button text="Base Button" /> <Button text="Highlighted Button" isHighlighted /> <Button text="Danger Button" isHighlighted variant="danger" /> <Button text="Primary Button" variant="primary" /> </div> </div> ); }; export default App;
我們建立了幾個 Button 元件的副本,並傳遞不同的 props。這就是我們的應用程式現在的樣子。
現在,仔細看看「危險按鈕」。即使我們將 isHighlighted 傳入 true,突出顯示的命名空間也不會套用。最後提到了危險變體,因此將應用它。因此,該按鈕將具有紅色背景顏色。
我們可以直接從 App.jsx 覆寫此 Button 元件的樣式屬性。
import Button from "./components/Button"; const App = () => { return ( <div> <h1>StyleX by Meta</h1> <Button text="Get Started" /> </div> ); }; export default App;
在此範例中,覆蓋命名空間目前允許任何屬性。然而,StyleX 使我們能夠限制哪些屬性可以被覆寫。使用 TypeScript 時,此功能變得特別有用。
// Button.jsx import PropTypes from "prop-types"; const Button = ({ text }) => { return <button>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
此限制可確保只有 backgroundColor 和 color 屬性可以被覆寫。
如果您向上捲動到前面的範例程式碼,您將看到我們已將margin: "1rem" 樣式新增至3 個不同的命名空間- App.jsx 中的main、Button.jsx 中的反白顯示和主要。當我們使用 Devtools 檢查元素時,我們可以看到不同的元件(主容器、突出顯示的按鈕和主按鈕)附加相同的類別名,並且只有 1 個類別 x42y017 保留 margin: "1rem" 樣式。
這就是 StyleX 透過使用原子類顯著減小其包大小的方式。達到一定閾值後,不再產生新的類別;相反,他們只是重複使用現有的類別。
能夠在粒度層級覆蓋樣式真是太棒了!然而,任何給定的設計系統都需要支援設計標記和主題。這就是 StyleX 的用武之地。 StyleX 中主題 API 的設計直接受到 React Context API 的啟發。變數的定義預設值與 React Context 的建立方式類似,並且可以建立主題來為 UI 子樹的這些變數「提供」不同的值。
我們可以透過建立 x.stylex.js 檔案來建立全域樣式。確保遵循此命名約定。在此文件中,我們使用 stylex.defineVars,如下所示。
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: "black", color: "white", }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
我們指的是使用者首選的主題並將其設定為常數值 - DARK。此外,讓我們使用此顏色變數建立一個新主題。
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: { default: "black", ":hover": "blue", }, color: "white", }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
主題建立後,就可以像 StyleX 中的任何其他樣式一樣使用。
import PropTypes from "prop-types"; import * as stylex from "@stylexjs/stylex"; const styles = stylex.create({ base: { fontSize: 18, backgroundColor: { default: "black", ":hover": "blue", }, color: "white", width: { default: "100px", "@media (max-width: 476px)": "100%", }, }, }); const Button = ({ text }) => { return <button {...stylex.props(styles.base)}>{text}</button>; }; Button.propTypes = { text: PropTypes.string.isRequired, }; export default Button;
這就是我們如何分別在淺色和深色模式下看到與 myCustomTheme 相同的頁面。
萬歲!我們已經成功掌握了與 StyleX 合作的要點。感謝您閱讀本文。我希望它能讓您更好地理解什麼是 StyleX、Meta 是如何創建它以及如何使用它。請在評論部分或 Twitter 上分享您的想法/問題。如果您對這個部落格感興趣,如果您能給這篇文章點個讚(用您最喜歡的表情符號?),我將不勝感激。
平安✌
在 Topmate 上與我聯繫以進行面試準備
以上是解碼 StyleX:Meta 的尖端造型系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!