React是一個用於構建使用者介面的JavaScript庫。我們還可以藉助React Router將其擴充套件為構建多頁應用程式。這是一個第三方庫,可在我們的React應用程式中啟用路由。
在本教程中,我們將介紹使用React Router入門所需的一切。
初始化專案為了能夠繼續學習,您需要通過在終端中執行以下命令來建立一個新的react應用程式:
npx create-react-app react-router-guide
然後,將這些程式碼行新增到App.js檔案中。
在App.js中,
然後,在繼續之前,我們先回答一個重要問題:什麼是路由?
什麼是路由?路由是向用戶顯示不同頁面的能力。這意味著它可以通過輸入URL或單擊元素在應用程式的不同部分之間移動。
如您所知,預設情況下,React不帶路由。為了在我們的專案中啟用它,我們需要新增一個名為react-router的庫。
要安裝它,您將必須在終端中執行以下命令:
yarn add react-router-domornpm install react-router-dom
現在,我們已經成功安裝了react router,讓我們在下一部分開始使用它。
設定路由要在React應用中啟用路由,我們首先需要從react-router-dom匯入BrowserRouter。
App.js
它會將需要路由的所有內容儲存在我們的應用程式中。這意味著,如果需要在整個應用程式中進行路由,則必須使用BrowserRouter包裝更高層的元件。
順便說一句,您不必像我在這裡那樣將BrowserRouter重新命名為Router,我只是想保持可讀性。
只有router,還做不了很多事情,讓我們在下一節中新增一條路由。
渲染路由要渲染路由,我們必須從react-router-dom包中匯入Route元件。
然後,將其新增到我們要呈現內容的位置。路線元件具有多個屬性。但是在這裡,我們只需要路徑和渲染。
path:這是route的路徑。在這裡,我們使用 / 定義主頁的路徑。render:到達路由時將顯示內容。在這裡,我們將向用戶呈現歡迎訊息。在某些情況下,提供這樣的路由是完全可以的,但請想象一下,當我們需要處理真實元件時,使用render可能不是正確的解決方案。
那麼,我們該如何顯示一個真實的元件呢?好吧,Route元件還有另一個名為component的屬性。
讓我們對示例進行一些更新以了解其實際效果。
App.js
現在,我們的路由將不再載入訊息,而是載入Home元件。
為了獲得React Router的全部功能,我們需要有多個頁面和連結可以使用。我們已經有了頁面(如果需要,也可以使用元件),現在,讓我們新增一些連結以能夠在頁面之間進行切換。
使用連結切換頁面要新增到我們專案的連結,我們將再次使用React Router。
App.js
import React, { Fragment } from "react";import "./index.css"import { BrowserRouter as Router, Route, Link } from "react-router-dom";export default function App() { return ( <Router> <main> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> </nav> <Route path="/" exact component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> </main> </Router> );}const Home = () => ( <> <h1>Home</h1> <FakeText /> </>);const About = () => ( <> <h1>About</h1> <FakeText /> </>);const Contact = () => ( <> <h1>Contact</h1> <FakeText /> </>);
匯入連結後,我們必須稍微更新導航欄。
現在,React Router不再使用標籤和href,而是使用Link來進行切換,而無需重新載入頁面。
然後,我們需要新增兩條新路線:“關於”和“聯絡方式”,以便您也可以在頁面或元件之間進行切換。
現在,我們可以通過連結轉到應用程式的不同部分。但是,我們的路由器存在問題。即使我們切換到其他頁面,Home元件也會一直顯示。
原因是React Router將檢查定義的路徑是否以/開頭(如果是),它將呈現元件。
在這裡,我們的第一個路徑以/開頭,因此Home元件每次都會呈現。
但是,我們仍然可以通過將exact屬性新增到Route來更改預設行為。
App.js
<Route path="/" exact component={Home} />
現在,對home元件的路由添加了exact屬性,那麼只有與完整路徑匹配時才會呈現。
我們仍然可以通過用Switch包裝路由來告訴React Router一次只加載一條路由來增強它。
App.js
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; <Switch> <Route path="/" exact component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> </Switch>
現在,我們有了新的連結,讓我們使用它們來傳遞引數。
傳遞路由引數要在頁面之間傳遞資料,我們需要更新示例。
App.js
import React, { Fragment } from "react";import "./index.css"import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";export default function App() { const name = 'John Doe' return ( <Router> <main> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to={`/about/${name}`}>About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> </nav> <Switch> <Route path="/" exact component={Home} /> <Route path="/about/:name" component={About} /> <Route path="/contact" component={Contact} /> </Switch> </main> </Router> );}const Home = () => ( <> <h1>Home</h1> <FakeText /> </>);const About = ({ match: { params: { name } } }) => ( // props.match.params.name <> <h1>About {name}</h1> <FakeText /> </>);const Contact = () => ( <> <h1>Contact</h1> <FakeText /> </>);
如您在此處看到的,我們首先宣告一個新的常量名稱,該常量名稱將作為引數傳遞給About頁面。並且,我們將名稱附加到相應的連結。
這樣,我們現在必須通過調整其路徑以將名稱接收為引數path =“ / about /:name”來更新About路線。
現在,引數將作為About元件中的props接收,我們現在唯一要做的就是對props進行結構分解並獲取name屬性。順便說一下,{match:{params:{name}}}與props.match.params.name相同。
到目前為止,我們已經做了很多工作,但是,在某些情況下,我們不想使用連結在頁面之間導航。
有時,我們必須等待操作完成才能導航到下一頁。
讓我們在下一部分中處理這種情況。
以程式設計方式導航我們收到的props有一些便捷的方法可用於在頁面之間導航。
App.js
const Contact = ({history}) => ( <> <h1>Contact</h1> <button onClick={() => history.push('/') } >Go to home</button> <FakeText /> </>);
在這裡,我們從收到的props中提取history物件。它有一些方便的方法,例如goBack,goForward等。但是在這裡,我們將使用push方法來轉到主頁。
現在,讓我們處理重定向使用者的情況。
重定向到另一個頁面React Router還有另一個名為Redirect的元件,正如您猜到的,它可以幫助我們將使用者重定向到另一個頁面。
import { BrowserRouter as Router, Route, Link, Switch, Redirect } from "react-router-dom";const About = ({ match:{ params: { name } } }) => ( // props.match.params.name <> { name !== 'Foo' ? <Redirect to="/" /> : null } <h1>About {name}</h1> <FakeText /> </>);
現在,如果作為引數傳遞的名稱不等於Foo,則使用者將被重定向到主頁。
您可能會爭論為什麼我不使用props.history.push('/')重定向使用者?好吧,Redirect元件會替換頁面,因此使用者無法返回上一頁,但是使用push方法,它可以。同樣,您還可以使用props.history.replace('/')來模仿重定向行為。
現在,讓我們繼續處理使用者遇到不存在的路由時的情況。
重定向到404頁面要將使用者重定向到404頁面,您可以建立一個元件來顯示它,但是為了使事情簡單起見,我將僅顯示帶有render的訊息。
import React, { Fragment } from "react";import "./index.css"import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";export default function App() { const name = 'Foo' return ( <Router> <main> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to={`/about/${name}`}>About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> </nav> <Switch> <Route path="/" exact component={Home} /> <Route path="/about/:name" component={About} /> <Route path="/contact" component={Contact} /> <Route render={() => <h1>404: page not found</h1>} /> </Switch> </main> </Router> );}
我們新增的新路由將捕獲所有不存在的路徑,並將使用者重定向到404頁面。
現在,讓我們繼續前進,並在下一部分中學習如何保護我們的路由。
保護路由有很多方法可以保護通往React的路由。但是,在這裡,我僅檢查使用者是否已通過身份驗證並將其重定向到適當的頁面。
import React, { Fragment } from "react";import "./index.css"import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";export default function App() { const name = 'Foo' const isAuthenticated = false return ( <Router> <main> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to={`/about/${name}`}>About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> </nav> <Switch> <Route path="/" exact component={Home} /> { isAuthenticated ? <> <Route path="/about/:name" component={About} /> <Route path="/contact" component={Contact} /> </> : <Redirect to="/" /> } </Switch> </main> </Router> );}
如您所見,我聲明了一個模仿身份驗證的變數。然後,檢查使用者是否已通過身份驗證。如果是這種情況,請渲染受保護的頁面,否則將其重定向到主頁。
到目前為止,我們已經介紹了很多內容,但是它仍然是一個有趣的部分:路由鉤子Hooks。
讓我們進入最後一節,介紹Hooks。
路由hooks(useHistory,useParams,useLocation)路由hooks使事情變得容易得多。現在,以簡單而優雅的方式訪問歷史記錄,位置或引數。
useHistory
useHistory鉤子使我們可以訪問history物件,而無需從props中將其提取。
import { useHistory } from "react-router-dom";const Contact = () => { const { history } = useHistory(); return ( <> <h1>Contact</h1> <button onClick={ () => history.push('/') } >Go to home</button> </> )};
useParams
它可以幫助我們無需使用props物件就可以在URL上傳遞引數。
import { BrowserRouter as Router, Route, Link, Switch, useParams } from "react-router-dom";export default function App() { const name = 'Foo' return ( <Router> <main> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to={`/about/${name}`}>About</Link></li> </ul> </nav> <Switch> <Route path="/" exact component={Home} /> <Route path="/about/:name" component={About} /> </Switch> </main> </Router> );}const About = () => { const { name } = useParams() return ( // props.match.params.name <> { name !== 'Foo' ? <Redirect to="/" /> : null } <h1>About {name}</h1> <Route component={Contact} /> </> )};
useLocation
它返回代表當前URL的位置物件。
import { useLocation } from "react-router-dom";const Contact = () => { const { pathname } = useLocation(); return ( <> <h1>Contact</h1> <p>當前 URL: {pathname}</p> </> )};
最後
React Router是一個了不起的庫,它可以幫助我們從一個頁面轉到一個多頁面的應用程式(雖然它仍然是一個頁面),並且具有很高的可用性。現在,藉助路由hooks,您已經親眼目睹了它們的簡易性和優雅性,絕對是您下一個專案中需要考慮使用的。