十四、react路由
阿新 • • 發佈:2021-07-12
一、路由的使用
1 npm i -S react-router-dom
1、相關元件
- Route元件:指定路由展示元件相關資訊(元件渲染)
- path屬性:路由規則,這裡需要跟Link元件裡面to屬性的值一致
- component屬性:展示的元件
2、封裝NavLink元件
1、NavLink標籤是一個高亮顯示的導航標籤
2、NavLink標籤體內容是一個特殊的標籤屬性,通過this.props.children屬性可以獲取標籤體內容(即Home或About)
NavLink封裝
1 import React,{Component} from 'react' 2 import {NavLink} from 'react-router-dom' 3 4 export default class MyNavLink extends Component{ 5 render(){6 return( 7 <NavLink activeClassName="link-name" className="link-item" {...this.props}/> 8 ) 9 } 10 }
使用
1 <MyNavLink to="/home">Home</MyNavLink> 2 <MyNavLink to="/about">About</MyNavLink>
3、Switch元件
1 <Switch> 2 {/*Switch只渲染第一個匹配的元件*/} 3 <Route path="/home" component={Home}></Route> 4 <Route path="/home" component={Test}></Route> 5 <Route path="/about" component={About}></Route> 6 </Switch>
二、路由導航方式
1、宣告式導航
1 import React from "react"; 2 import ReactDOM from "react-dom"; 3 4 // 設定路由模式 5 import {HashRouter as Router} from 'react-router-dom' 6 7 // 定義 provider 8 import { Provider } from "react-redux"; 9 import store from "./Store/index"; 10 11 import App from "./App"; 12 13 ReactDOM.render( 14 <Provider store={store}> 15 // 使用Router包裹根元件 16 <Router> 17 <App></App> 18 </Router> 19 </Provider>, 20 document.getElementById("root") 21 );
1 import React, { Component } from "react"; 2 import { HashRouter as Router, Route, Link } from "react-router-dom"; 3 4 import Cmp10 from "./Components/Cmp10"; 5 import Cmp11 from "./Components/Cmp11"; 6 7 class App extends Component { 8 render() { 9 return ( 10 <Router> 11 <div> 12 <h1>導航區域</h1> 13 <div> 14 <ul> 15 <li> 16 <Link to="/home">首頁</Link> 17 </li> 18 <li> 19 <Link to="/news">新聞</Link> 20 </li> 21 </ul> 22 </div> 23 </div> 24 <Route path="/home" component={Cmp10}></Route> 25 <Route path="/news" component={Cmp11}></Route> 26 </Router> 27 ); 28 } 29 } 30 export default App;
需要注意:
1 <MyNavLink replace to="/home">Home</MyNavLink>
1 this.props.history.push({ 2 pathname: "/home", 3 search: "from=404", // 表示傳遞查詢字串 4 state: { // 隱式傳參,位址列不體現 5 username: "admin", 6 }, 7 }); 8 9 this.props.history.go(-1)
不要在根元件中使用程式設計式導航。
三、路由匹配
1、模糊匹配與嚴格匹配
模糊匹配(預設)
1 {/*MyNavLink中的/about/a/b匹配到Route中的/about"*/} 2 <MyNavLink to="/home">Home</MyNavLink> 3 <MyNavLink to="/about/a/b">About</MyNavLink> 4 5 <Switch> 6 <Route path="/home" component={Home}></Route> 7 <Route path="/home" component={Test}></Route> 8 <Route path="/about" component={About}></Route> 9 </Switch>
嚴格匹配:exact屬性
1 <MyNavLink to="/home">Home</MyNavLink> 2 <MyNavLink to="/about/a/b">About</MyNavLink> 3 4 <Switch> 5 <Route exact path="/home" component={Home}></Route> 6 <Route exact path="/home" component={Test}></Route> 7 <Route exact path="/about" component={About}></Route> 8 </Switch>
2、重定向路由
React的重定向路由有以下兩種寫法:
方式一:推薦
1 import { Redirect } from "react-router-dom" 2 3 <Redirect from="/from" to="/to"></Redirect> 4 <Route path="/to" component={xxxx}></Route>
方式二 :不推薦
1 import { Route, Redirect } from "react-router-dom" 2 3 <Route path="/from"> 4 <Cmp></Cmp> 5 <Redirect to="/to" /> 6 </Route>
3、404路由
專案中少不了404頁面的配置,在React裡面配置404頁面需要注意:
1 import NotFound from "./Components/404"; 2 3 <Route> 4 <NotFound></NotFound> 5 </Route> 6 // 或 7 <Route component={NotFound}></Route>
- 並不會因為當前是404路由/重定向路由而改變狀態碼,因為當前寫的是前端的內容,狀態碼是後端提供的,只有等後期上線以後才能有狀態碼。
1 <div> 2 <Link to="/home">家</Link>   3 <Link to="/news">新聞</Link>  4 <Link to="/about">關於</Link>  5 <Redirect from="/" to="/home"></Redirect> 6 <Switch> 7 <Route path="/home" component={Cmp11}></Route> 8 <Route path="/news" component={Cmp12}></Route> 9 <Route path="/about" component={Cmp13}></Route> 10 <Route component={NotFound}></Route> 11 </Switch> 12 </div>
四、巢狀路由
在有一些功能中,往往請求地址的字首是相同的,不同的只是後面一部份,此時就可以使用多級路由(路由巢狀)來實現此路由的定義實現。
例如,路由規則如下
1 admin/user 2 admin/goods
1 <Route path="/admin" component={Admin}></Route>
- 建立模組路由元件負責指定各個路由的去向
1 render() { 2 // 獲取字首,供後續地址做路由拼接 3 let prefix = this.props.match.path; 4 return ( 5 <div> 6 <h1>歡迎使用後臺管理程式</h1> 7 <Route path={`${prefix}/user`} component={User}></Route> 8 <Route path={`${prefix}/goods`} component={Goods}></Route> 9 </div> 10 ); 11 }
五、路由懶載入
優化效能,讓路由按需載入
1 import React, {Component, lazy, Suspense} from 'react' 2 import {NavLink, Route} from 'react-router-dom' 3 4 // Loading用於懶載入元件未加載出來的展示 5 import Loading from './Loading' 6 7 // import Home from './Home' 8 // import News from './News' 9 10 const Home = lazy(() => {import('./Home')}) 11 const News = lazy(() => {import('./News')}) 12 13 export default class Demo extends Component{ 14 <div> 15 <h1>導航區域</h1> 16 <div> 17 <ul> 18 <li> 19 <Link to="/home">首頁</Link> 20 </li> 21 <li> 22 <Link to="/news">新聞</Link> 23 </li> 24 </ul> 25 </div> 26 <Suspense fallback={<Loading/>}> 27 <Route path="/home" component={Home}></Route> 28 <Route path="/news" component={News}></Route> 29 </Suspense> 30 </div> 31 }
六、路由引數
路由引數:在Route定義渲染元件時給定動態繫結的引數。
React路由傳參方式有三種:
1、動態路由引數(param)
1 <Link to={`/film/detail/${detailObj.id}`}></Link>
在目標頁面路由中傳遞
1 <Router path="/film/detail/:id" component={Detail}></Router>
3、
- 不適合寫在宣告式導航中,寫在程式設計式導航中更加合適
1 <Link to={{pathname:`/film/detail`,state={id:detailObj.id,title:detailObj.title}}}></Link>
- 埋點資料
1 constructor(props){ 2 super(props) 3 this.state = { 4 // 接收動態路由引數 5 news_id: this.props.match.params.id, 6 // 接收查詢字串並處理 7 query: querystring.parse(this.props.location.search.slice(1)), 8 // 接收state 9 state: this.props.location.state 10 }; 11 }
七、路由三種渲染方式
1 <Route path="/home" component={Home} />
1 <Route path="/home" component={() => <Home />} />
2、render屬性(函式)
1 <Route path="/home" render={props => <Home />} />
3、
1 <Route path="/about" children={props => { 2 if(props.match){ 3 return <div>children渲染</div> 4 } 5 }} />
1 <Route path="/about" children={<About />} />
注意
- component可以使用元件類渲染或內聯方式渲染,render只能使用函式,children使用函式或直接使用元件
- 當children的值是一個函式時,無論當前地址和path路徑匹不匹配,都將會執行children對應的函式,當children的值為一個元件時,當前地址和path不匹配時,路由元件不渲染
- children函式方式渲染,會在形參中接受到一個物件,物件中match屬性如果當前地址匹配成功返回物件,否則null
- children函式方式渲染,在自定義導航元件的上面會非常好用
八、withRouter高階元件
作用:把不是通過路由切換過來的元件中,將react-router 的 history、location、match 三個物件傳入props物件上
- 預設情況下,必須是經過路由匹配渲染的元件才存在this.props才擁有路由引數,才能使用程式設計式導航的寫法,才能執行this.props.history.push('/uri')跳轉到對應路由的頁面
- 然而不是所有元件都直接與路由相連的,當這些元件需要路由引數時,使用withRouter就可以給此元件傳入路由引數,此時就可以使用this.props
1 // 引入withRouter 2 import { withRouter} from 'react-router-dom' 3 4 // 執行一下withRouter 5 export default withRouter(Cmp)
該高階元件是路由包自帶的東西,因此只需要引入+使用就可以了,不需要自己定義。
九、自定義導航元件
1 import React, { Component, Fragment } from "react"; 2 import { Route } from "react-router-dom" 3 // 引入自定義導航元件 4 import MyLink from "./Components/MyLink" 5 import Cmp1 from "./Components/Cmp1"; 6 import Cmp2 from "./Components/Cmp2"; 7 8 class App extends Component { 9 render() { 10 return ( 11 <Fragment> 12 <MyLink tag="h1" to="/cmp1"> 13 去1 14 </MyLink> 15 <MyLink tag="h1" to="/cmp2"> 16 去2 17 </MyLink> 18 <Route path="/cmp1" component={Cmp1}></Route> 19 <Route path="/cmp2" component={Cmp2}></Route> 20 </Fragment> 21 ); 22 } 23 } 24 export default App;
自定義導航元件參考
1 import React, { Component, Fragment } from "react"; 2 import { withRouter, Route } from "react-router-dom"; 3 4 class MyLink extends Component { 5 // 點選跳轉動作 6 goUrl = () => { 7 this.props.history.push(this.props.to); 8 }; 9 render() { 10 // 獲取引數 11 var Tag = this.props.tag ? this.props.tag : "a"; 12 return ( 13 <Fragment> 14 <Route 15 path={this.props.to} 16 children={({ match }) => { 17 if (match) { 18 // 匹配 19 return ( 20 <Tag 21 onClick={this.goUrl} 22 style={{ color: "red" }} 23 > 24 {this.props.children} 25 </Tag> 26 ); 27 } else { 28 // 不匹配 29 return ( 30 <Tag onClick={this.goUrl}> 31 {this.props.children} 32 </Tag> 33 ); 34 } 35 }}> 36 </Route> 37 </Fragment> 38 ); 39 } 40 } 41 42 export default withRouter(MyLink);
十、樣式引入問題
css樣式引入:public檔案下自定義樣式引入
- 導航方式:BrowserRouter改成HashRouter