React学习笔记七——React-router-web的使用详解

理解

  • 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指定的路由
<Redirect to="/home" />

嵌套路由

在这里插入图片描述

嵌套路由代码案例

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

在这里插入图片描述

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可以用来解决一些路径错误相关的问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端探险家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值