sx —— 樣式速寫
このコンテンツはまだ日本語訳がありません。
sx 是 lh-ui 的內聯樣式速寫:用 mt: 4 代替 style="margin-top: 32px",用 p: 2 代替一次性寫四邊 padding。它不是 Tailwind(不生成類別名、不引 CSS),而是執行時把屬性包直接求值為 Record<string, string>,交給 UI 層綁到 :style。
- 元件庫內部:
sx讓元件在「版面配置微調」這一層不必新增 prop——<LhButton sx={{ mt: 2 }} />就能頂開上方間距。 - 需要隨資料動態變化的間距:數值到 px 的換算(
×8)讓「離我近一點」這類語義有了穩定刻度。 - 不該用它:成體系的視覺設計。sx 是「呼叫點的臨時微調」,主題色、控制項高度這類設計令牌仍然走 CSS 變數(見 主題系統);sx 裡寫
color: 'var(--lh-primary-color)'能工作,但更推薦讓元件直接消費令牌。
// 精確匯入(推薦,tree-shaking 友善)import { sxToStyle, mergeSx } from '@lh-ui/share/core/shared/sx'import type { LhSxProps } from '@lh-ui/share/core/shared/sx'
// 或從聚合入口import { sxToStyle } from '@lh-ui/share/core/shared'| 函式 | 簽名 | 傳回 | 作用 |
|---|---|---|---|
sxToStyle |
(sx: LhSxProps) => Record<string, string> |
內聯樣式物件 | 把 sx 屬性包求值為 CSS 樣式 |
mergeSx |
(...list: (LhSxProps | undefined | null)[]) => LhSxProps |
合併後的 sx | 後者覆蓋前者,供 UI 層組合「預設 sx + 呼叫方 sx」 |
sxToStyle 的優先級規則
Section titled “sxToStyle 的優先級規則”「單邊 > 軸組 > 簡寫」,且與鍵的書寫順序無關。實作上按 簡寫 → 軸組 → 單邊 的固定順序寫入樣式物件,後寫覆蓋先寫,所以無論你怎麼排鍵序:
sxToStyle({ m: 2, mt: 4 }) // { marginTop: '32px', marginRight: '16px', marginBottom: '16px', marginLeft: '16px' }sxToStyle({ mt: 4, m: 2 }) // 完全相同sxToStyle({ my: 2, mt: 4 }) // marginTop 單邊勝出:32px;mb 仍是 16px這條規則讓元件庫可以安全地寫「預設包 + 使用者覆蓋」:使用者傳的 mt 一定會壓過元件內部的 m。
- 數值按
×8px換算:mt: 4→32px。8 是 lh-ui 的間距基準(與--lh-spacing-*令牌同刻度)。 - 字串原樣透傳:
w: '50%'→50%,p: '1rem'→1rem。 - 版面配置類鍵不換算:
display/flex/flexDirection/alignItems/justifyContent的值按字串直接寫入(flexDirection: 'column'不會變成columnpx)。 - 所有鍵統一按
!== undefined判定:傳空串''視為顯式清空,會被寫入。
export interface LhSxProps { // 尺寸 w?: string | number h?: string | number // 外邊距:單邊 / 軸組 / 簡寫 mt?: string | number mr?: string | number mb?: string | number ml?: string | number my?: string | number mx?: string | number m?: string | number // 內邊距:同構 pt?: string | number pr?: string | number pb?: string | number pl?: string | number py?: string | number px?: string | number p?: string | number // 版面配置 display?: string flex?: string flexDirection?: 'row' | 'column' alignItems?: string justifyContent?: string // 相容下游自訂鍵;未知鍵會被靜默丟棄 [key: string]: any}索引簽名 [key: string]: any 是刻意的:各 UI 庫會在自己的 LhXxxProps 裡把 sx?: LhSxProps 與元件特有屬性放在一起,索引簽名讓類型不互相衝突;未知鍵在求值時被丟棄,不會洩漏進樣式。
sxToStyle({ mt: 2, px: 3, display: 'flex', alignItems: 'center' })// {// marginTop: '16px',// paddingLeft: '24px',// paddingRight: '24px',// display: 'flex',// alignItems: 'center',// }<!-- Vue3 / Vue2:直接綁 :style --><template> <lh-button :style="sxToStyle($props.sx)">按鈕</lh-button></template>// React<div style={sxToStyle({ my: 4, w: '100%' })} />// uniapp:sxToStyle 輸出的是普通物件,直接進 style 綁定// (數值 ×8px 在非 h5 端需要視平台換算,UI 層自行處理)mergeSx 的典型用法是元件內部組合預設值:
// 元件內部const merged = mergeSx({ py: 2, px: 4 }, props.sx) // 使用者的 sx 覆蓋預設const style = sxToStyle(merged) // 只求值一次,優先級規則只結算一遍mergeSx是淺合併(Object.assign),不遞迴;sx 的值都是標量,淺合併夠用。sxToStyle假值傳回{}:sxToStyle(undefined)是空物件,UI 層可以無腦呼叫。- 數值換算的 8px 基準與令牌體系對齊,但 sx 本身不引用 CSS 變數——它產出的是計算好的字面值,適合「這一次呼叫要偏一點」的場景,不適合「隨主題變」的場景。
- 跨端:uniapp 非 h5 端的 rpx 需在 UI 層換算,sx 內核只出 px。
@lh-ui/share/core/sx → sxToStyle( )返回值
(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue