【全栈React】第13天: 重复元素
本文轉載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3826
原文:https://www.fullstackreact.com/30-days-of-react/day-13/
今天,我們將通過如何顯示多個組件來準備將外部數據引入我們的應用。
我們已經構建了一個沒有任何外部數據的基本應用。在我們實現之前 (我們將在明天開始這個功能), 讓我們來看看過去兩周中我們所掩蓋的事情:
重復元素
我們已經看到了這之前, 我們已經遍歷了一個對象列表, 并在屏幕上呈現多個組件。在我們的應用中添加太多的復雜度來加載外部數據之前, 今天我們將快速了解如何在應用中重復組件/元素。
由于 jsx 被瀏覽器視為純 javascript 的, 我們可以使用任何 傳統 javascript 內的模板標簽中的 jsx。我們已經看到了這一行動。作為一個快速演示:
const App = (props) => {return (<ul>{a.map(i => {return <li>{i}</li>})}</ul>) }注意模板標簽{} 內的內容看起來簡單的 javascript。那是因為它 只是 javascript。此功能允許我們使用 (大多數) 的 javascript 在我們的模板標簽 包括 原生迭代器, 如 map和 forEach 。
讓我們來看看這是什么意思。讓我們將上一個示例的 a 值從單個整數轉換為整數列表:
const a = [1, 10, 100, 1000, 10000];我們可以將 a 變量映射到我們的組件中, 并返回將為我們構建虛擬 DOM 的響應組件列表。
const App = (props) => {return (<ul>{a.map(i => {return <li>{i}</li>})}</ul>) }什么是map() 函數?
map() 函數是數組中一個原生javascript內置函數的。
它接受在數組的每個元素上運行的函數, 因此, 上面的函數將運行四次, 其值為i 開始為1 , 然后它將再次運行它的第二個值, i將被設置為10 等等等等。
讓我們更新我們在第12天創建的應用與我們的 App 組件在這里。讓我們打開我們的src/App.js 文件, 并將 App 組件的內容替換為此源。清理一些未使用的變量和您的src/App.js應該類似于以下內容:
import React from 'react';const a = [1, 10, 100, 1000, 10000]; const App = (props) => {return (<ul>{a.map(i => {return <li>{i}</li>})}</ul>) }export default App使用create-react-app命令生成的命令再次啟動應用:npm start, 我們可以看到應用在瀏覽器中工作!
但是, 如果我們打開開發人員控制臺, 我們將看到打印出錯誤。此錯誤是由以下事實引起的: React不知道如何跟蹤我們列表中的各個組件, 因為它們只是看起來像一個 <li />組件。
出于性能原因, React使用虛擬 DOM 嘗試限制在重新視圖時需要更新的 DOM 元素的數量。如果沒有任何變化, React不會使瀏覽器更新任何東西以節省工作。
此功能非常適合于構建 web 應用, 但有時我們必須通過為節點提供唯一標識符來幫助做出React。在映射列表和渲染組件是其中之一。
React要求我們通過使用特殊屬性來識別惟一的組件, 這是列表中每個元素的 key 屬性。key 屬性可以是任何我們想要的, 但它 必須是唯一的 的元素。在我們的示例中, 我們可以在 map 中使用i變量, 因為數組中沒有其他元素具有相同的值。
讓我們更新映射來設置key:
const App = (props) => {return (<ul>{a.map(i => {return <li key={i}>{i}</li>})}</ul>) }子組件
我們在本周早些時候談到了建立父子關系的事情, 但是讓我們更詳細地介紹一下如何訪問父組件中的子組件, 以及如何呈現它們。
在第11天, 我們構建了一個 <Formatter />組件來處理時鐘組件中的日期格式, 以使用戶能夠靈活地使用自己的自定義時鐘渲染。回想一下, 我們所創建的實現實際上是相當丑陋和相對復雜的。
const Formatter = (props) => {let children = props.format.split('').map((e, idx) => {if (e === 'h') {return <Hour key={idx} {...props} />} else if (e === 'm') {return <Minute key={idx} {...props} />} else if (e === 's') {return <Second key={idx} {...props} />} else if (e === 'p') {return <Ampm key={idx} {...props} />} else if (e === ' ') {return <span key={idx}> </span>;} else {return <Separator key={idx} {...props} />}});return <span>{children}</span>; }我們可以用React.Children 對象來映射一個React對象的列表, 并讓React做這個自舉。其結果是一個更干凈的 Formatter組件 (不是完美的, 但可使用的):
const Formatter = ({format, state}) => {let children = format.split('').map(e => {if (e == 'h') {return <Hour />} else if (e == 'm') {return <Minute />} else if (e == 's') {return <Second />} else if (e == 'p') {return <Ampm />} else if (e == ' ') {return <span> </span>;} else {return <Separator />}});return (<span>{React.Children.map(children, c => React.cloneElement(c, state))}</span>) }React.cloneElement
我們還沒有談論React.cloneElement() 函數, 所以讓我們簡單地看看它。
記得 WWWWWAAAAAYYYYY(way) 回到第2天, 我們看了如何瀏覽器 看待 JSX? 它把它變成了類似于如下的 javascript:
React.cloneElement() 為我們處理這個。有時我們會想復制它或添加自定義props/children的組件,而不是創建一個新的組件實例 (如果我們已經有一個)。所以我們可以保留它創建的相同的屬性。我們可以用React.cloneElement() 來為我們處理這一切。
React.cloneElement() 和React.createElement() 函數有相同的api,參數所在的位置:
在我們的 Formatter 示例中, 我們正在創建列表中所有子級 (<Hour />, <Minute />等組件) 并將state 對象作為其屬性。
React.Children 的對象提供了一些很好的實用工具來處理children的函數。上面的 Formatter 示例使用 map 函數循環訪問子級, 并在列表中克隆每一個。它為每一個創建一個key (如果需要), 使我們不必自己管理唯一性。
讓我們使用React.Children.map() 函數更新我們的應用組件:
const App = (props) => {return (<ul>{React.Children.map(a, i => <li>{i}</li>)}</ul>) }在瀏覽器中, 一切仍然正常。
在 React.Children 中還有其他一些非常有用的方法,我們將主要使用React.Children.map() 函數,但了解其他可用的 對我們來說也是很好的。 點擊文檔 查看更多列表。
通過這一點, 我們只處理了本地數據, 而不是真正關注遠程數據 (盡管我們在構建活動提要組件時 已經 簡要地提到了它)。明天, 我們將進入與服務器的互動, 所以我們可以使用它在我們的React應用。
今天的工作很棒!
總結
以上是生活随笔為你收集整理的【全栈React】第13天: 重复元素的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 背水一战 Windows 10 (55)
- 下一篇: MetaModelEngine:域模型定