您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關怎么用React Router 4構建通用JavaScript應用的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
React Router 是一個在 React 領域非常流行的庫。它依靠位置欄上的請求 URL 和 瀏覽器的操作歷史來渲染不同的頁面內容來保持顯示,進而將你的 app 同步到用戶接口的頁面上。
最近,版本4的 React Router 已經進入 beta 發布階段。損譽各半,React Router 的這一次發布是對上一版本的完整重寫,這導致了很多破壞性的 API 變更。
在版本 4 的核心理念是 “聲明式可組合性(declarative composability)”?—— 它包含 React 之所以優秀的組件概念,并將其應用于 routing。React Router 4 的每一個部分都是 React 的組件: Router , Route , Link 等等。
React Router 的一位開發者, Ryan Florence ,親手制作了一個簡短的視頻來介紹***的 React Router,這段視頻獲得了很多人的推薦:
視頻: https://youtu.be/a4kqMQorcnE
新版本的 React Router 奉上了一個新的 web 頁面,上面有 許多實用的代碼示例 ,但沒有提供實例介紹如何在服務端使用 React Router 來進行基于 React 的頁面的渲染。
對于我近期正在進行的項目,對搜索引擎友好且具備***的網站運行速度是重中之重,難道這樣就要在客戶端渲染整個頁面?難道就用示例頁面上所有實例所采取的辦法?那是不可取的。我們要使用一個 Express 服務器來在后臺對 React 頁面進行渲染。
在其介紹視屏中, Ryan 有一個可以從某些 API 獲取數據來初始化其狀態的 App 組件, 使用的是 componentDidMount 生命周期方法。但異步數據的獲取操作完畢,組件就會被更新以顯示數據。
但是當要在服務端對 App 組件進行渲染的時候這樣做不會有效果: 在你使用 renderToString 的時候, 帶有 HTML 代碼的字符串在調用了組件的渲染方法之后就會被同步地創建出來。 componentDidMount 從未被調用到。
因此如果我們使用 Ryan 視頻里的示例在后臺渲染出 App 組件,它只會生成一條 “Loading…” 消息。
作為對概念方案的驗證,我創建了一個 demo 應用,基本上就是對視頻中 Ryan 的示例進行重造,但采取的是服務器端的渲染。
應用使用了 GitHub API 去獲取有關于 Gist 代碼片段的數據:
你可以在 Github 上找到 demo 應用的源代碼:
https://github.com/technology-ebay-de/universal-react-router4
簡而言之,下面就是我所做的事情…
這就是每次有 HTTP 請求發到 Express 服務器的時候都會跑一次的代碼:
const routes = ['/','/g/:gistId']; app.get('*', (req, res) => { const match = routes.reduce((acc, route) => matchPath(req.url, route, { exact: true }) || acc, null);if (!match) { res.status(404).send(render(<NoMatch />));return; } fetch('https://api.github.com/gists') .then(r => r.json()) .then(gists => res.status(200).send(render( ( <StaticRouter context={{}} location={req.url}> <App gists={gists} /> </StaticRouter> ), gists )) ).catch(err => res.status(500).send(render(<Error />)); }); app.listen(3000, () => console.log('Demo app listening on port 3000'));
(注意:這里只是摘錄,你可以在 GitHub 找到完整的源代碼 )
在第 1–4行 , 我為 app 定義了一個路由數組。數組的***個元素就是針對主頁的初始請求, 沒有 Gists 被選上。第二個路由就是用來展示一個被選上的 Gist 的。
在第 6行 , 我的 Express app 被告知要處理任何可以使用星號匹配上的請求。
在第 7行 , 我使用了來自于 React Router 的 matchPath 函數對路由數組進行簡省; 結果就是一個匹配對象,其擁有關于能匹配到的路由以及任何可以從 URL 路徑轉換過來的參數,這些信息。
在第 8–11行 , 如果有不能匹配的路由,我就渲染出一個錯誤頁面,上面會說 : “頁面沒找到(Page not found)”。
這里的 render 函數只是圍繞 React 的 renderToString 的一個封裝而已,添加了包圍 React 組件的 HTML 的基礎頁面的 HTML 代碼 ( <html> , <head> , <body> , 等等)。
在第 12–22行 , 我會從 GitHub API 獲取到可以填充 App 狀態的數據,并且對 App 組件進行渲染。
最顯而易見是第 17 行,我使用了 StaticRouter 組件來初始化 React Router。該 Router 組件類型是采用服務端渲染方案的***選擇。它永遠不會改變位置, 這是我們在本場景下所需要的, 因為是在后臺上, 我們只會渲染一次,而且不會直接地對用戶的交互操作做出反應。
而第 23 行 會捕獲在處理期間產生的錯誤信息來渲染出一個錯誤頁面。
我的 App 組件看起來像下面這樣:
export default ({ gists }) => (<div><Sidebar>{ gists ? gists.map(gist => (<SidebarItem key={gist.id}><Link to={`/g/${gist.id}`}>{gist.description || '[no description]'}</Link></SidebarItem>)) : (<p>Loading…</p>) }</Sidebar><Main><Route path="/" exact component={Home} />{ gists && (<Route path="/g/:gistId" render={ ({ match }) => (<Gist gist={gists.find(g => g.id === match.params.gistId)} /> ) } /> ) }</Main></div>);
(→ GitHub上有完整的源代碼 )
在第 1 行 , 組件接收到作為一個屬性的 Gist 數據對象。
第 3–13行 渲染了一個 Sidebar 組件,里面是連接到不同 Gist 鏈接。 SidebarItem 組件里面所包含的是只有在存在實際的 Gist 數據時才會被渲染的數據。在服務端,總會有這樣的情況發生。而我們在服務端和客戶端渲染中都會用到該組件。如果組件是在客戶端被渲染的, 我們可能處在獲取新的 Gist 數據這一過程之中,所以會展示出一條 “Loading…(加載中)” 的消息。
第 15行 使用了一個來自于 React Router 庫的 Route 組件,用以在路由匹配到“/”這個路徑的時候展示出 Home 組件。這里我們使用的是精確匹配, 不然的話任何以斜線開頭的路徑都會匹配到。
如果有 Gist 數據要展示的話, 那么在第 18 行 , 另外一個 Route 組件就會被用來展示一個 Gist 組件,上面是被選擇的 Gist 的詳細信息。
如前所述,這是一個 通用 JavaScript 應用(大家都知道的“同構”),意思是相同的代碼即可用于渲染服務器頁面,又可以用于渲染客戶端頁面。這里摘錄了一段在客戶端初始化頁面的代碼:
render((<BrowserRouter><App gists={window.__gists__} /> </BrowserRouter> ), document.getElementById('app'));
(→ GitHub 上的完整代碼 )
這比服務端代碼簡單多了! 第 1 行 的 render 函數就是 ReactDOM 的 render 函數 。它把我的 React 組件渲染出來的布局附加到 DOM 節點上。
第 2 行 使用了 BrowserRouter (代替了我在服務端進行渲染使用的 StaticRouter)。
第 3 行 我使用 gist 數據對 App 組件進行實例化,以此代替通過 GitHub API 獲取數據。gist 數據來自瀏覽器 DOM 的全局變量,它是后端通過 <script> 標簽放在那里的。
感謝各位的閱讀!關于“怎么用React Router 4構建通用JavaScript應用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。