天天看點

React學習筆記七——React-router-web的使用詳解了解React-router-web相關的API嵌套路由路由傳參程式設計式路由導航withRouterBrowserRouter和HashRouter的差別

了解

  • React的一個插件庫
  • 專門用來實作一個SPA應用
  • 基于React的項目都會使用到此庫

React-router-web相關的API

< Link >

  • 在React中靠酷遊連結去切換元件
//案例

import { Link } from 'react-router-dom'
//路由跳轉連結
<Link to="/about">About</Link>
           

< BrowserRouter >

import { BrowserRouter } from 'react-router-dom'

//把APP内的路由元件都交給一個路由管理
<BrowserRouter> 
  <App/>
</BrowserRouter>

           

< Route >

import { Route } from 'react-router-dom'

<Route  path="/home" component={Home}/>

<Route path="/user/:username" component={User}/>
const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}
           

< NavLink>

  • 一個特殊版本的 Link,當它與目前 URL 比對時,為其渲染元素添加樣式屬性
import { NavLink } from 'react-router-dom'

// 實作導航連結高亮展示,顯示預設顔色
<NavLink to="/about">About</NavLink>

//自定義選中樣式
<NavLink
  to="/about"
  activeClassName="selected"  
>About</NavLink>


//内聯方式自定義選中樣式
<NavLink
  to="/about"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
  }}
>About</NavLink>


//在樣式中設定選中樣式
.selected{
   background-color:xxx !importent; //必須添加!importent 提高樣式權限
   color:xxx !importent;
}

           

< Switch>

  • 渲染與該位址比對的第一個子節點 或者
  • 多個路由的話使用
import { Switch, Route } from 'react-router'

<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/user" component={User}/>//比對到第一個user路由元件,顯示該元件
  <Route path="/user" component={test}/>//不顯示該元件
</Switch>
           

< Redirect >

  • 渲染 将使導航到一個新的位址。這個新的位址會覆寫 history 棧中的目前位址
  • 一般寫在路由的最下方,當所有路由無法比對時,跳轉到Redirect指定的路由

嵌套路由

React學習筆記七——React-router-web的使用詳解了解React-router-web相關的API嵌套路由路由傳參程式設計式路由導航withRouterBrowserRouter和HashRouter的差別

嵌套路由代碼案例

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

// 路由元件
const Main = () => <h2>Main</h2>;
const Sandwiches = () => <h2>Sandwiches</h2>;
const Tacos = ({ routes }) => (
  <div>
    <h2>Tacos</h2>
    <ul>
      <li>
        <Link to="/tacos/bus">Bus</Link>
      </li>
      <li>
        <Link to="/tacos/cart">Cart</Link>
      </li>
    </ul>
    
    {routes.map((route, i) => <RouteWithSubRoutes key={i} {...route} />)}
  </div>
);
const Bus = () => <h3>Bus</h3>;
const Cart = () => <h3>Cart</h3>;


// 路由配置
const routes = [
  {
    path: "/sandwiches",
    component: Sandwiches
  },
  {
    path: "/tacos",
    component: Tacos,
    routes: [
      {
        path: "/tacos/bus",
        component: Bus
      },
      {
        path: "/tacos/cart",
        component: Cart
      }
    ]
  }
];

//對路由元件容器的二次封裝
const RouteWithSubRoutes = route => (
  <Route
    path={route.path}
    render={props => (
      <route.component {...props} routes={route.routes} />
    )}
  />
);

const RouteConfigExample = () => (
  <Router>
    <div>
      <ul>
        <li>
          <Link to="/tacos">Tacos</Link>
        </li>
        <li>
          <Link to="/sandwiches">Sandwiches</Link>
        </li>
      </ul>
      
      {routes.map((route, i) => <RouteWithSubRoutes key={i} {...route} />)}
    </div>
  </Router>
);

export default RouteConfigExample;
           

路由傳參

向路由元件傳遞params參數

  • 路由連結(攜帶參數):< link to="/demo/tom/18"></ link >
  • 注冊路由(接收參數):< Route path="/demo/:name/:age" component={Test}></ Route >
  • 接收參數:const {name ,age} = this.props.match.params
React學習筆記七——React-router-web的使用詳解了解React-router-web相關的API嵌套路由路由傳參程式設計式路由導航withRouterBrowserRouter和HashRouter的差別
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const ParamsExample = () => (
  <Router>
    <div>
      <h2>Accounts</h2>
      <ul>
        <li>
          <Link to="/netflix">Netflix</Link>
        </li>
        <li>
          <Link to="/zillow-group">Zillow Group</Link>
        </li>
        <li>
          <Link to="/yahoo">Yahoo</Link>
        </li>
        <li>
          <Link to="/modus-create">Modus Create</Link>
        </li>
      </ul>

      <Route path="/:id" component={Child} />

    </div>
  </Router>
);

const Child = ({ match }) => (
  <div>
    <h3>ID: {match.params.id}</h3>
  </div>
);


export default ParamsExample;
           

向路由元件傳遞search參數

  • 路由連結(攜帶參數): < Link to="/demo?id=$ {info.id}&name=${info.name}" >{info.name}</ Link >
  • 注冊路由(無需接收參數): < Route path="/demo" component={Demo} />
  • 接受參數:const {search} = this.props.location , const {id,name} = qs.parse(search.slice(1))
備注:路由元件接受參數由于是search參數:"?id=Netflix&name=Netflix"(urlencoded編碼字元串),是以需要一個【querystring庫】轉化成"{id:‘Netflix’,name:‘Netflix’}"的格式
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
//不用安裝,react腳手架已經下載下傳好了,直接引入用
//将“?id=Netflix&name=Netflix”轉換成一個對象{id:'Netflix',name:'Netflix'}的庫
import qs from "querystring"; 

//舉例子說明querystring庫的使用
let obj= {name:'tom',age:18}
console.log(qs.stringify(obj)) //name=tom&age=18  urlencoded編碼
let str = "name=tom&age=18"
console.log(qs.parse(str)) // {name:'tom',age:18}

export default class Test extends React.Component {
  state = {
    infos:[
	  {id:'Netflix',name:'Netflix'},
	  {id:'Zillow Group',name:'Zillow Group'}
	]
  }
  render(){
   const {infos} = this
    return (
     <Router>
	    <div>
	      <h2>Accounts</h2>
	      <ul>
	        {
	          infos.map((info) => {
	            return (
	             <li>
	               <Link to="/demo?id=${info.id}&name=${info.name}">{info.name}</Link>
	             </li>
	            )
	          })
	        }
	      </ul>
	       {/* search參數無需接受 */}
	      <Route path="/demo" component={Demo} />
	    </div>
	  </Router>
    )
  }
}  

class Demo extends React.Component{
 const {search} = this.props.location
 const {id,name} = qs.parse(search.slice(1))
 render(){
   return (
      <div>
	    <h3>ID: {id}</h3>
	    <h3>NAME: {name}</h3>
	  </div>
   )
 }
}  
           

向路由元件傳遞state參數

  • 路由連結(攜帶參數): < Link to={{pathname:’/demo’,state:{id:info.id,name:info.name}}} >{info.name}</ Link >
  • 注冊路由(無需接收參數): < Route path="/demo" component={Demo} />
  • 接受參數: const {id,name} = this.props.location.sate
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

export default class Test extends React.Component {
  state = {
    infos:[
	  {id:'Netflix',name:'Netflix'},
	  {id:'Zillow Group',name:'Zillow Group'}
	]
  }
  render(){
   const {infos} = this
    return (
     <Router>
	    <div>
	      <h2>Accounts</h2>
	      <ul>
	        {
	          infos.map((info) => {
	            return (
	             <li>
	               <Link to={{pathname:'/demo',state:{id:info.id,name:info.name}}} >{info.name}</Link>
	             </li>
	            )
	          })
	        }
	      </ul>
	       {/* state參數無需接受 */}
	      <Route path="/demo" component={Demo} />
	    </div>
	  </Router>
    )
  }
}  

class Demo extends React.Component{
  //接收state參數
  const {id,name} = this.props.location.sate
 render(){
   return (
      <div>
	    <h3>ID: {id}</h3>
	    <h3>NAME: {name}</h3>
	  </div>
   )
 }
}  
           

程式設計式路由導航

最常用的方法:replace()、push()、goback()、go()

注意隻有路由元件才能使用以上程式設計式路由導航

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

export default class Test extends React.Component {
  state = {
    infos:[
	  {id:'Netflix',name:'Netflix'},
	  {id:'Zillow Group',name:'Zillow Group'}
	]
  }
  clickKip = (id,name) => {
    this.props.history.push(`/demo/${id}/${name}`) //無曆史記錄的跳轉,可以回退
    this.props.history.replace(`/demo/${id}/${name}`) //替換路由跳轉
  }
  render(){
   const {infos} = this
    return (
     <Router>
	    <div>
	      <h2>Accounts</h2>
	      <ul>
	        {
	          infos.map((info) => {
	            return (
	             <li>
	               <Link onClick={()=>this.clickKip(info.id,info.name)}>{info.name}</Link>
	             </li>
	            )
	          })
	        }
	      </ul>
	       {/* state參數無需接受 */}
	      <Route path="/demo" component={Demo} />
	    </div>
	  </Router>
    )
  }
}  

class Demo extends React.Component{
  //接收state參數
  const {id,name} = this.props.match.params
 render(){
   return (
      <div>
	    <h3>ID: {id}</h3>
	    <h3>NAME: {name}</h3>
	  </div>
   )
 }
}  
           

withRouter

您可以通過 withRouter 高階元件通路 history 對象的屬性和最近的 的 match 。 當路由渲染時, withRouter 會将已經更新的 match , location 和 history 屬性傳遞給被包裹的元件。

import React from "react";
import { withRouter } from "react-router-dom";

//一般元件
class Demo extends React.Component{
 ...
}  

export default withRouter(Demo )
           
  • withRouter的傳回值是一個新元件;
  • withRouter可以加工一般元件,讓一般元件擁有路由元件所特有的API,可以向路由元件一樣可以通路到match , location 和 history 屬性,元件内也可以使用程式設計式導航;

BrowserRouter和HashRouter的差別

1.底層原理不一樣

  • BrowserRouter使用的是H5的history的API,不相容IE9以及以下的版本
  • HashRouter使用的是url的哈希值

2.url表現形式不一樣

  • BrowserRouter的路徑上沒有#,例如: http://localhost:3005/demo
  • HashRouter的路徑帶#,例如: http://localhost:3005/#/demo

3.重新整理後對路由state參數的影響

  • BrowserRouter沒有任何影響,因為state儲存在history對象中
  • HashRouter重新整理後會導緻state參數的丢失

4.備注:HashRouter可以用來解決一些路徑錯誤相關的問題