無頭組件只是一個無樣式組件,還是還有更多內容?
網絡已經通過要求定義樣式來將樣式與內容分開
在 css 中而不是 html 中。這種架構允許每個網頁都采用全局
設計標準,無需定義任何特定于頁面的樣式。
隨著網絡演變成一個應用程序平臺,開發人員尋找方法
他們不斷增長的代碼庫更易于維護。如今,事實上的策略是
組織應用程序代碼就是定義小型、輕量級的組件,這些組件可以
一起組成。因此,組件成為
中的組成單位
現代網絡開發。
為了封裝,組件通常會同時定義 html 和 css。
雖然這使它們更容易創作,但它們也可能更難
緊密結合到現有的設計系統中。這一點尤其正確
對于從外部供應商進口的第三方組件。
無頭組件通過重新引入
之間的分離來解決這一挑戰
內容和風格。然而現在分離是沿著組件邊界的
反對 html 和 css 之間的關系。它們是創建出色的無頭組件的關鍵
關鍵在于設計組件的接口,以便開發人員可以
清晰、輕松地應用自己的風格。
轉發相關道具
從最基本的意義上來說,無頭組件只是一個無樣式的組件。
開發人員必須能夠將自己的 css 應用到 html 元素中
組件定義.
對于簡單的組件,這可能只是轉發 classname 的問題
prop 到根元素,以便開發人員可以在他們的
中使用類選擇器
css.
如果你的組件與原生 html 元素具有相同的語義,你可以使用
來自 react 的 componentprops 類型,以確保所有相關的 props
可轉發。請記住省略任何您不希望用戶使用的道具
您的組件能夠覆蓋。
import { type componentprops } from 'react' function submitbutton({ ...props }: omit<componentprops>, 'type'>) { return <button type="submit"></button> } </componentprops>
登錄后復制
提供預定義類
對于包含一個或多個子元素的組件,開發者可能會
想要單獨設置每個元素的樣式。
支持這一點的一個策略是依賴
css 組合器。
例如,無頭畫廊組件的樣式可能如下:
/* root container */ .gallery { } /* gallery items container */ .gallery > ul { } /* gallery item */ .gallery > ul > li { } /* next and previous buttons */ .gallery button { }
登錄后復制
但是這種方法產生了一個巨大的問題,因為現在
的內部 html 結構
該組件是其公共 api 的一部分。這會阻止您修改
稍后構建,而不會破壞下游代碼。
更好的策略是為每個主要子元素預定義類。這邊
開發人員可以使用類選擇器,而不依賴于任何特定的 html
結構:
.xyz-gallery { } .xyz-gallery-next-button { } .xyz-gallery-previous-button { } .xyz-gallery-items-container { } .xyz-gallery-item { }
登錄后復制
記住給你的類添加前綴,這樣它們就不會與
沖突
開發者自己的風格。
支持自定義布局
提供預定義的類可能是使開發人員能夠實現的最快方法
設置你的組件的樣式。然而,這種方法的一個缺點是
html 結構無法自定義。
這可能并不重要。畢竟,純 html 的使用方式已經相當靈活了
可以渲染。然而,有時開發人員會按順序獲取額外的 html
來完成某些設計。如果您查看幾乎所有的源代碼
網站,您可能會看到大量無語義的
元素,
其唯一目的是定義彈性或網格布局,直觀地對子項進行分組
邊框內的元素或創建新的堆疊上下文。
您可以通過將無頭組件拆分為
來支持此類用例
多個相關組件。這樣開發者就可以自由添加自己的
將元素布局到組件。例如,開發人員可以嵌入 next 和
自定義 flexbox 容器中圖庫示例中的上一個按鈕:
<gallery><galleryitems classname="gallery-items-container"> {data.map((item) => ( <galleryitem key="{item.id}">{item.content}</galleryitem> ))} </galleryitems><div classname="gallery-buttons-container"> <gallerypreviousbutton><gallerynextbutton></gallerynextbutton></gallerypreviousbutton> </div> </gallery>
登錄后復制
.gallery-items-container { } .gallery-buttons-container { display: flex; gap: 0.5rem; justify-content: flex-end; }
登錄后復制
這些類型的組件通常使用
實現
要傳遞的上下文
它們之間的數據。他們需要更多的工作來設計、實施和
文檔。然而,它們所帶來的多功能性通常意味著額外的努力
值得。
允許組件被覆蓋
少數用例需要無頭組件管理布局
其子組件。一個例子可能是層次樹視圖
允許通過拖放對其項目進行重新排序。另一個用例可能是
允許單頁應用程序用 a 替換默認的錨元素
有助于客戶端路由的自定義鏈接組件。
允許開發人員定義自定義布局的高級策略是
允許通過 props 覆蓋正在渲染的實際子組件:
<treeview nodes="{[...]}" components="{{" customrow customdragpreview:><div classname="drag-preview"></div> }} /> </treeview>
登錄后復制
這使開發人員可以完全控制每個子項中渲染的內容
組件,同時允許無頭組件管理其整體
結構.
您甚至可以允許開發人員自定義組件的根元素
通過道具。例如,這個按鈕組件允許開發者渲染它
作為其他東西:
import { type elementtype } from 'react' function headlessbutton({ as, ...props }: { as?: elementtype }) { const component = as ?? 'button' return <component></component> }
登錄后復制
例如,為了讓輔助技術將按鈕視為鏈接,
開發人員可以指定應該使用錨元素來渲染
按鈕:
<headlessbutton as="a">Actually a link</headlessbutton>
登錄后復制
概括
無頭組件比不包含任何組件的組件要多得多
風格。優秀的無頭組件是完全可擴展的,并允許開發人員
自定義整個內部 html 結構。