?
Dokumen ini menggunakan Manual laman web PHP Cina Lepaskan
在我們看來,React 是用 JavaScript 構(gòu)建大型、快速 Web 應用程序的主要方式。它在 Facebook 和 Instagram 上對我們的擴展非常好。
React 的許多重要組成部分之一就是如何讓您在構(gòu)建應用程序時考慮應用程序。在本文中,我們將引導您使用 React 構(gòu)建可搜索產(chǎn)品數(shù)據(jù)表的思考過程。
想象一下,我們已經(jīng)有了一個 JSON API 和來自我們設(shè)計師的模擬器。模擬看起來像這樣:
我們的 JSON API 返回一些如下所示的數(shù)據(jù):
[ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}];
你要做的第一件事是在模擬中的每個組件(和子組件)周圍繪制框,并給它們所有名稱。如果您正在與設(shè)計師合作,他們可能已經(jīng)完成了這項工作,請與他們談?wù)?!他們?Photoshop 圖層名稱可能最終會成為您的React組件的名稱!
但你怎么知道自己的組件應該是什么?只需使用相同的技巧來決定是否應創(chuàng)建新的函數(shù)或?qū)ο?。一種這樣的技術(shù)是單一責任原則,也就是說,一個組件理想地只應該做一件事。如果它最終增長,它應該被分解成更小的子組件。
由于您經(jīng)常向用戶顯示 JSON 數(shù)據(jù)模型,因此您會發(fā)現(xiàn),如果您的模型構(gòu)建正確,那么您的 UI(以及您的組件結(jié)構(gòu))將很好地映射。這是因為UI和數(shù)據(jù)模型傾向于遵循相同的信息架構(gòu),這意味著將 UI 分解為組件的工作通常是微不足道的。只需將其分解為完全代表您的數(shù)據(jù)模型的一部分的組件。
您會在這里看到我們的簡單應用中有五個組件。我們已將每個組件代表的數(shù)據(jù)以斜體表示。
FilterableProductTable
(橙色):包含整個示例
SearchBar
(藍色):接收所有用戶輸入
ProductTable
(綠色):根據(jù)用戶輸入顯示和過濾數(shù)據(jù)收集
ProductCategoryRow
(綠松石):為每個類別顯示標題
ProductRow
(紅色):顯示每個產(chǎn)品的一行
如果你看一下ProductTable
,你會發(fā)現(xiàn)表頭(包含“名稱”和“價格”標簽)不是它自己的組件。這是一個偏好的問題,有兩種方法都有爭論。對于這個例子,我們將它作為其一部分,ProductTable
因為它是呈現(xiàn)數(shù)據(jù)收集的一部分,這是ProductTable
責任。然而,如果這個頭部變得復雜(即,如果我們要為分類添加可供性),將它作為它自己的ProductTableHeader
組件將是有意義的。
現(xiàn)在我們已經(jīng)確定了模擬中的組件,讓我們將它們安排到一個層次結(jié)構(gòu)中。這很容易。出現(xiàn)在模擬中另一個組件中的組件應該在層次結(jié)構(gòu)中顯示為一個子組件:
FilterableProductTable
- `SearchBar`- `ProductTable`
- `ProductCategoryRow` - `ProductRow`
見筆思維陣營:第2步上CodePen。
現(xiàn)在您已經(jīng)擁有組件層次結(jié)構(gòu),現(xiàn)在可以實施您的應用了。最簡單的方法是構(gòu)建一個接收數(shù)據(jù)模型并呈現(xiàn) UI 但不具有交互性的版本。最好解耦這些過程,因為構(gòu)建一個靜態(tài)版本需要大量的輸入和思考,而添加交互性需要大量的思考,而不是大量的輸入。我們會看到為什么。
要構(gòu)建呈現(xiàn)數(shù)據(jù)模型的應用程序的靜態(tài)版本,您需要構(gòu)建可重用其他組件并使用道具傳遞數(shù)據(jù)的組件。道具是一種將數(shù)據(jù)從父母傳遞給孩子的方式。如果您熟悉狀態(tài)的概念,請不要使用狀態(tài)來構(gòu)建此靜態(tài)版本。狀態(tài)僅用于交互性,即隨時間變化的數(shù)據(jù)。由于這是應用程序的靜態(tài)版本,因此您不需要它。
您可以構(gòu)建自上而下或自下而上。也就是說,您可以從構(gòu)建層次結(jié)構(gòu)中較高級的組件(即以開始FilterableProductTable
)或以較低的組件(ProductRow
)開始構(gòu)建組件。在更簡單的例子中,自上而下通常會更容易,而在大型項目中,自下而上和編寫測試時更容易。
在這一步結(jié)束時,您將擁有一個可重用組件的庫,用于呈現(xiàn)您的數(shù)據(jù)模型。組件只會有render()
方法,因為這是您的應用程序的靜態(tài)版本。層次結(jié)構(gòu)頂部的組件(FilterableProductTable
)將把您的數(shù)據(jù)模型作為一個道具。如果您對基礎(chǔ)數(shù)據(jù)模型進行了更改并ReactDOM.render()
再次調(diào)用,則UI將會更新。很容易看到你的UI如何更新以及在哪里進行更改,因為沒有任何復雜的事情發(fā)生。React 的單向數(shù)據(jù)流(也稱為單向綁定)可以保持一切模塊化和快速。
如果您需要幫助執(zhí)行此步驟,請參閱 React 文檔。
React 中有兩種“模型”數(shù)據(jù):道具和狀態(tài)。了解兩者之間的區(qū)別很重要; 如果您不確定區(qū)別是什么,請瀏覽官方的 React 文檔。
為了使您的 UI 交互,您需要能夠觸發(fā)對基礎(chǔ)數(shù)據(jù)模型的更改。React 使狀態(tài)變得簡單。
要正確構(gòu)建應用程序,首先需要考慮應用程序需要的最小可變狀態(tài)集。這里的關(guān)鍵是 DRY:不要重復自己。找出您的應用程序需要的狀態(tài)的絕對最小表示形式,并計算您需要的其他所有內(nèi)容。例如,如果您正在創(chuàng)建一個 TODO 列表,只需保留一組 TODO 項目; 不要為計數(shù)保留一個單獨的狀態(tài)變量。相反,當您要渲染 TODO 計數(shù)時,只需簡單計算 TODO 項目數(shù)組的長度。
考慮我們示例應用程序中的所有數(shù)據(jù)。我們有:
產(chǎn)品的原始列表
用戶輸入的搜索文本
復選框的值
過濾的產(chǎn)品列表
我們來看看每一個,并確定哪一個是狀態(tài)。只需詢問關(guān)于每一條數(shù)據(jù)的三個問題:
它是通過道具從父數(shù)據(jù)傳入嗎?如果是這樣,它可能不是陳述。
它隨著時間的推移而保持不變嗎 如果是這樣,它可能不是陳述。
你能基于組件中的任何其他狀態(tài)或道具來計算它嗎?如果是這樣,那不是陳述。
原來的產(chǎn)品清單是作為道具傳入的,所以這不是狀態(tài)。搜索文本和復選框似乎是狀態(tài)的,因為它們隨著時間而改變并且不能從任何東西計算。最后,過濾后的產(chǎn)品列表不是狀態(tài),因為它可以通過將原始產(chǎn)品列表與復選框的搜索文本和值組合來計算。
最后,我們的狀態(tài)是:
用戶輸入的搜索文本
復選框的值
請參閱筆反思:在CodePen上的第4 步。
好的,我們已經(jīng)確定了最少的應用程序狀態(tài)集。接下來,我們需要確定哪個組件變異或擁有這個狀態(tài)。
請記住:React 是關(guān)于組件層次結(jié)構(gòu)下的單向數(shù)據(jù)流。它可能不會立即清楚哪個組件應該擁有什么狀態(tài)。對于新手來說,這通常是最具挑戰(zhàn)性的部分,所以請按照以下步驟來弄清楚:
對于你的應用程序中的每一個狀態(tài):
確定每個基于該狀態(tài)呈現(xiàn)某些內(nèi)容的組件。
找到一個共同的擁有者組件(一個單獨的組件超出了所有需要該層次中狀態(tài)的組件)。
無論是共同所有者,還是等級較高的其他組成部分都應擁有該州。
如果你無法找到一個有意識擁有這個狀態(tài)的組件,可以創(chuàng)建一個新的組件,只是為了保存狀態(tài)并將它添加到公共所有者組件上方的層次結(jié)構(gòu)中的某處。
讓我們來看看我們的應用程序的這個策略:
ProductTable
需要根據(jù)狀態(tài)過濾產(chǎn)品列表,同時SearchBar
需要顯示搜索文本和選中狀態(tài)。
共同的所有者組件是FilterableProductTable
。
從概念上講,過濾器文本和檢查值可以存在 FilterableProductTable
所以我們決定我們的國家居住在英國FilterableProductTable
。首先,添加一個實例屬性this.state = {filterText: '', inStockOnly: false}
到FilterableProductTable
's constructor
來反映你的應用程序的初始狀態(tài)。然后,通過filterText
與inStockOnly
以ProductTable
和SearchBar
為道具。最后,使用這些道具過濾行中ProductTable
并設(shè)置表單域的值SearchBar
。
你可以開始看到你的應用程序?qū)⑷绾伪憩F(xiàn):設(shè)置filterText
到"ball"
和刷新您的應用程序。您會看到數(shù)據(jù)表已正確更新。
見筆思維陣營:第5步上CodePen。
到目前為止,我們已經(jīng)構(gòu)建了一個應用程序,可以根據(jù)道具和狀態(tài)正確地呈現(xiàn)在層次結(jié)構(gòu)中?,F(xiàn)在是時候以另一種方式支持數(shù)據(jù)流:深層次中的表單組件需要更新狀態(tài)FilterableProductTable
。
React 使這個數(shù)據(jù)流清晰易懂,以便理解你的程序如何工作,但它確實需要比傳統(tǒng)的雙向數(shù)據(jù)綁定更多的輸入。
如果您嘗試在當前版本的示例中鍵入或選中該框,您會看到 React 忽略了您的輸入。這是故意的,因為我們已經(jīng)設(shè)置value
的道具input
總是等于state
從傳遞FilterableProductTable
。
讓我們思考我們想要發(fā)生的事情。我們希望確保每當用戶更改表單時,我們都會更新狀態(tài)以反映用戶輸入。由于組件應該只更新自己的狀態(tài),FilterableProductTable
因此SearchBar
只要狀態(tài)應該更新,就會傳遞回調(diào)。我們可以使用onChange
輸入中的事件來通知它。通過的回調(diào)FilterableProductTable
將會調(diào)用setState()
,并且應用程序?qū)⒈桓隆?/p>
雖然這聽起來很復雜,但它只是幾行代碼。這真的很明確你的數(shù)據(jù)如何在整個應用程序中流動。
希望這可以讓你了解如何使用 React 構(gòu)建組件和應用程序。雖然它可能比您習慣的輸入要多一些,但請記住,代碼的讀取遠遠大于其編寫的代碼,并且讀取此模塊化的顯式代碼非常容易。當你開始構(gòu)建大型組件庫時,你會明白這種明確性和模塊性,并且隨著代碼的重用,你的代碼行將開始縮小。