看看HTML狀態
讓我們選擇一個簡單的例子 – 裡面有一個簡單的複選框的幾個標籤。但是,無論簡單性如何,都應該讓它變得更加複雜,然後優化方法,使每一步都變得更好。
我們試試吧 終極版
, 的setState
, useState
而……結局將是……出乎意料的。
TL; DR https://codesandbox.io/s/romantic-http-h6cgj
該應用程序
讓我們假設我們的 應用
會是這樣的
功能 應用() { 返回 ( <DIV 班級名稱=「APP」> <TabHeader> <標籤 ID={1}>一</標籤> <標籤 ID={2}>二</標籤> <標籤 ID={3}>三</標籤> </ TabHeader> <TabContext> <標籤 ID={1}> 內容 的 TAB1 <複選框 /> </標籤> <標籤 ID={2}> 內容 的 TAB2 <複選框 /> </標籤> <標籤 ID={3}> 內容 的 TAB3 <複選框 /> </標籤> </ TabContext> </ DIV> ); }
我希望第一個例子儘可能地惡化,但我認為這就夠了……
終極版
O Redux,國家的狀態你統治真理的唯一來源,為我們所有人派遣貨物。
當然使用Redux來處理Tab組件是一個正確的決定,只要Redux總是一個正確的決定。
// TabHeader只是渲染所有內容 常量 TabHeader = ({ 孩子 }) => <部分>{孩子}</節>; //「無狀態/啞」選項卡組件 常量 TabImplementation = ({ 孩子, ONSELECT }) => <DIV 的onClick={ONSELECT}>{孩子}</ DIV>; //所有邏輯都在TabContext中 常量 TabContextImplementation = ({ 孩子, selectedTab }) => ( <部分> {應對。孩子。地圖(孩子, (兒童) => ( //僅顯示「已選中」的孩子 selectedTab === 兒童。道具。ID ? 兒童 : 空值 ))} </部分> ) //連接Tab,提供`onSelect`動作 常量 標籤 = 連(空值, (調度, ownProps) => ({ ONSELECT: () => 調度(selectTab(ownProps。ID)) }))(TabImplementation); //連接TabContext,從狀態讀取`selectedTab` 常量 TabContext = 連(州 => ({ selectedTab: 州。selectedTab }))(TabContextImplementation);
這實際上是非常簡單的例子 終極版
可以為您的組件布線,以及它有多酷。
但是,你知道,對於這樣一個簡單的例子,我們可能不需要這麼複雜的代碼。讓我們優化
組件狀態
要使用自己的組件狀態,我們只需要刪除對redux的綁定,然後重新連接 應用
,使其成為有狀態的組成部分。
類 應用 擴展 應對。零件 { 州 = { selectedTab: 1 }; ONSELECT = (selectedTab) => 這個。的setState({selectedTab}); 給予 () { 返回 ( <DIV 班級名稱=「APP」> <TabHeader> <標籤 ID={1} ONSELECT={() => 這個。ONSELECT(1)}>一</標籤> <標籤 ID={2} ONSELECT={() => 這個。ONSELECT(1)}>二</標籤> <標籤 ID={3} ONSELECT={() => 這個。ONSELECT(1)}>三</標籤> </ TabHeader> <TabContent selectedTab={這個。州。selectedTab}> <標籤 ID={1}> 內容 的 TAB1 <複選框 /> </標籤> <標籤 ID={2}> 內容 的 TAB2 <複選框 /> </標籤> <標籤 ID={3}> 內容 的 TAB3 <複選框 /> </標籤> </ TabContent> </ DIV> ); } }
這就是我們需要的所有國家管理。它會更簡單嗎?
鉤
將 掛鉤
讓它變得更好?是!他們將即使差異很小,從可讀性的角度來看也是巨大的。
常量 應用 = () => { 常量 (selectedTab, 的setSelected) = useState(1); 返回 ( <DIV 班級名稱=「APP」> <TabHeader> <標籤 ID={1} ONSELECT={useCallback(() => 的setSelected(1))}>一</標籤> <標籤 ID={2} ONSELECT={useCallback(() => 的setSelected(1))}>二</標籤> <標籤 ID={3} ONSELECT={useCallback(() => 的setSelected(1))}>三</標籤> </ TabHeader> <TabContent selectedTab={selectedTab}> <標籤 ID={1}> 內容 的 TAB1 <複選框 /> </標籤> <標籤 ID={2}> 內容 的 TAB2 <複選框 /> </標籤> <標籤 ID={3}> 內容 的 TAB3 <複選框 /> </標籤> </ TabContent> </ DIV> ); }
我們做到了?
第一個和最後一個例子之間的區別是……不同。所需的代碼量幾乎相同,優點無可比擬,可讀性在任何情況下都是完美的。
唯一的區別在於「組件化」 – 使用本地狀態並掛鉤選項卡 州
與Redux是本地的,它是全球性的。它既不壞也不好,兩者都能滿足你的需求。
我們忘了什麼嗎?
我們做了一個偉大的反應工作,但是一個糟糕的html工作。附上 的onClick
div的處理程序是一個最糟糕的想法 – 它絕對無法訪問。
有沒有辦法處理「狀態」,並在同一時間使應用程序「可訪問」?
HTML狀態
讓我先向您展示代碼,然後我將解釋它是如何工作的
常量 TabHeader = ({ 孩子, 組 }) => ( <> {應對。孩子。地圖(孩子, (兒童, 指數) => ( //我們將「狀態」存儲在單選按鈕中 <輸入 類=「隱藏輸入選項卡控制輸入」 defaultChecked={指數 === 0} 名稱={組} 類型=「無線電」 ID={`控制 -${兒童。道具。控制}`} /> ))} <導航>{孩子}</導航> </> ); 常量 標籤 = ({ 孩子, 控制 }) => ( //選項卡不是通過`div`,`button`或`a`來控制的 //選項卡通過附加到輸入的「LABEL」和選項卡本身進行控制 <標籤 htmlFor={`控制 -${控制}`} 詠嘆調-控制={控制}> {孩子} </標籤> ); 常量 TabContent = ({ 孩子, 組 }) => ( <部分 班級名稱=「標籤」> {應對。孩子。地圖(孩子, (兒童, 指數) => ( <部分 類=「標籤截面」 ID={兒童。道具。ID}>{兒童。道具。孩子}</部分> ))} </部分> ); 常量 複選框 = () => <輸入 類型=「複選框」 />; 常量 應用 = () => ( <DIV 班級名稱=「APP」> <TabHeader 組=「標籤」> <標籤 控制=「TAB1」>一</標籤> <標籤 控制=「TAB2」>二</標籤> <標籤 控制=「TAB3」>三</標籤> </ TabHeader> <TabContent> <標籤 ID=「TAB1」> 內容 的 TAB1 <複選框 /> </標籤> <標籤 ID=「TAB2」> 內容 的 TAB2 <複選框 /> </標籤> <標籤 ID=「TAB3」> 內容 的 TAB3 <複選框 /> </標籤> </ TabContent> </ DIV> );
總而言之,根本沒有國家管理,它比以前更好。只要 redio-按鈕
同 標籤
和 標籤
,與它們沒有多大關係……我不確定它是如何工作的 – 但它確實有效。
這是證明 – 沙箱的鏈接 – https://codesandbox.io/s/romantic-http-h6cgj
更具體一點 – 它的功能與觸及標籤一樣 – 嘗試它,它是一樣的。這是真正的無障礙體驗,Reach非常熱衷於此。
但 到達的UI
必須處理鍵盤事件和焦點管理,以使標籤按照應有的方式工作 – 只有 活性
tab-header是可聚焦的,您可以通過按來更改選項卡 剩下
/對
。
你可能不相信 – 我的例子它將完全相同。
秘密
秘密在於CSS – 每一個 輸入
在視覺上隱藏。所以它存在,它是可以中心化的,但是看不見的。其他一切都在使用 輸入
州。
// 輸入 1 是 檢查? 然後 標籤 1 應該 是 可見。 .TAB控制輸入:檢查:第n型-(1) 〜 .tabs .TAB節:第n型-(1){ 顯示: 塊; } // 和 標籤 應該 是 膽大 如果 相應 無線電 按鍵 是 活性 .TAB控制輸入:檢查:第n型-(1) 〜 導航 標籤:第n型-(1){ 字體重量: 600; } // 和 焦點 環 應該 是 遠距傳物 至 一個 標籤 .TAB控制輸入:焦點:第n-的型(1) 〜 導航 標籤:第n型-(1) { 大綱: 瘦 點; 大綱: 為5px 汽車 -webkit對焦環的顏色; }
結構存在局限性 – 〜
運營商需求 輸入
在一邊,和 標籤
+ 標籤
另外一個。這意味著所有輸入都在左側,所有選項卡都在右側。結果是這樣的
。標籤-控制-輸入:檢查 〜 。標籤 。標籤-部分 { 顯示: 塊; }
會顯示所有 .tabs
任何 輸入
檢查,只要他們都符合條件。
在這個例子中我使用過 :第n的式(N)
,但最好是動態生成CSS(CSS-in-JS),有更多獨特的選擇器,比如 #category-women-clothing:checked~div nav label(for =「category-women-clothing」)
(來自theurge的代碼片段),或 輸入0-0-1
就像在Reach中一樣。
結論
所以,驚喜 HTML可以是您的狀態管理,您將獲得更多語義和更容易獲得的結果。玩了一會兒:)
你知道 – 使用平台:)你可能會錯過一些東西。