第五章 React 路由
 
五、向路由组件传递参数数据
 
1. 效果
 

 
2. 代码 - 传递 params 参数
 
2.1 Message
 
import React, { Component } from "react";
import {Link, Route} from 'react-router-dom'
import Detail from './Detail'
export default class Message extends Component {
  state = {
    messageArr: [
      {id:'01', title: '消息1'},
      {id:'02', title: '消息2'},
      {id:'03', title: '消息3'},
    ]
  }
  render() {
    const {messageArr} = this.state
    return (
      <div>
        <ul>
          {
            messageArr.map((msgObj)=>{
              return (
                <li key={msgObj.id}>
                  {}
                  <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <hr />
        {}
        <Route path="/home/message/detail/:id/:title" component={Detail}/>
      </div>
    );
  }
}
 
2.2 Detail
 
import React, { Component } from 'react'
const Detaildata = [
    {id:'01', content:'你好,中国'},
    {id:'02', content:'你好,小帽学堂'},
    {id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
  render() {
    
    const {id, title} = this.props.match.params
    const findResult = Detaildata.find((detailObj)=>{
        return detailObj.id === id
    })
    return (
      <ul>
        <li>ID:{id}</li>
        <li>Title:{title}</li>
        <li>Content: {findResult.content}</li>
      </ul>
    )
  }
}
 
3. 代码 - 传递 search 参数
 
3.1 Message
 
import React, { Component } from "react";
import {Link, Route} from 'react-router-dom'
import Detail from './Detail'
export default class Message extends Component {
  state = {
    messageArr: [
      {id:'01', title: '消息1'},
      {id:'02', title: '消息2'},
      {id:'03', title: '消息3'},
    ]
  }
  render() {
    const {messageArr} = this.state
    return (
      <div>
        <ul>
          {
            messageArr.map((msgObj)=>{
              return (
                <li key={msgObj.id}>
                  {}
                  {}
                  {}
                  <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <hr />
        {}
        {}
        {}
        <Route path="/home/message/detail" component={Detail}/>
      </div>
    );
  }
}
 
3.2 Detail
 
import React, { Component } from 'react'
import qs from 'querystring'
const Detaildata = [
    {id:'01', content:'你好,中国'},
    {id:'02', content:'你好,小帽学堂'},
    {id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
  render() {
    
    
    
    const {search} = this.props.location
    const {id, title} = qs.parse(search.slice(1))
    const findResult = Detaildata.find((detailObj)=>{
        return detailObj.id === id
    })
    return (
      <ul>
        <li>ID:{id}</li>
        <li>Title:{title}</li>
        <li>Content: {findResult.content}</li>
      </ul>
    )
  }
}
 
4. 代码 - 传递 state 参数
 
4.1 Message
 
import React, { Component } from "react";
import {Link, Route} from 'react-router-dom'
import Detail from './Detail'
export default class Message extends Component {
  state = {
    messageArr: [
      {id:'01', title: '消息1'},
      {id:'02', title: '消息2'},
      {id:'03', title: '消息3'},
    ]
  }
  render() {
    const {messageArr} = this.state
    return (
      <div>
        <ul>
          {
            messageArr.map((msgObj)=>{
              return (
                <li key={msgObj.id}>
                  {}
                  {}
                  {}
                  {}
                  {}
                  <Link to={{pathname:'/home/message/detail', state:{id:msgObj.id, title: msgObj.title}}}>{msgObj.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <hr />
        {}
        {}
        {}
        {}
        {}
        <Route path="/home/message/detail" component={Detail}/>
      </div>
    );
  }
}
 
4.2 Detail
 
import React, { Component } from 'react'
const Detaildata = [
    {id:'01', content:'你好,中国'},
    {id:'02', content:'你好,小帽学堂'},
    {id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
  render() {
    
    
    
    
    
    
    const {id, title} = this.props.location.state || {}
    const findResult = Detaildata.find((detailObj)=>{
        return detailObj.id === id
    }) || {}
    return (
      <ul>
        <li>ID:{id}</li>
        <li>Title:{title}</li>
        <li>Content: {findResult.content}</li>
      </ul>
    )
  }
}
 
5. 总结
 
1.params参数
	路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
	注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
	接收参数:this.props.match.params
2.search参数
	路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
	注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
	接收参数:this.props.location.search
	备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3.state参数
	路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
	注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
	接收参数:this.props.location.state
	备注:刷新也可以保留住参数
 
6. 代码 - push 与 replace 模式
 
Message
 
import React, { Component } from "react";
import {Link, Route} from 'react-router-dom'
import Detail from './Detail'
export default class Message extends Component {
  state = {
    messageArr: [
      {id:'01', title: '消息1'},
      {id:'02', title: '消息2'},
      {id:'03', title: '消息3'},
    ]
  }
  render() {
    const {messageArr} = this.state
    return (
      <div>
        <ul>
          {
            messageArr.map((msgObj)=>{
              return (
                <li key={msgObj.id}>
                  {}
                  {}
                  {}
                  {}
                  {}
                  <Link replace to={{pathname:'/home/message/detail', state:{id:msgObj.id, title: msgObj.title}}}>{msgObj.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <hr />
        {}
        {}
        {}
        {}
        {}
        <Route path="/home/message/detail" component={Detail}/>
      </div>
    );
  }
}
 
六、多种路由跳转方式
 
1. 效果
 

 
2. 代码 - 跳转 + 携带 params 参数
 
2.1 Message
 
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Detail from "./Detail";
export default class Message extends Component {
  state = {
    messageArr: [
      { id: "01", title: "消息1" },
      { id: "02", title: "消息2" },
      { id: "03", title: "消息3" },
    ],
  };
  pushShow = (id, title) => {
    
    this.props.history.push(`/home/message/detail/${id}/${title}`)
  }
  replaceShow = (id, title) => {
    
    this.props.history.replace(`/home/message/detail/${id}/${title}`)
  }
  render() {
    const { messageArr } = this.state;
    return (
      <div>
        <ul>
          {messageArr.map((msgObj) => {
            return (
              <li key={msgObj.id}>
                {}
                <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>
                  {msgObj.title}
                </Link>
                 <button onClick={()=>this.pushShow(msgObj.id, msgObj.title)}>push查看</button>
                 <button onClick={()=>this.replaceShow(msgObj.id, msgObj.title)}>replace查看</button>
              </li>
            );
          })}
        </ul>
        <hr />
        {}
        <Route path="/home/message/detail/:id/:title" component={Detail} />
      </div>
    );
  }
}
 
2.2 Detail
 
import React, { Component } from 'react'
const Detaildata = [
    {id:'01', content:'你好,中国'},
    {id:'02', content:'你好,小帽学堂'},
    {id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
  render() {
    
    const {id, title} = this.props.match.params
    const findResult = Detaildata.find((detailObj)=>{
        return detailObj.id === id
    }) || {}
    return (
      <ul>
        <li>ID:{id}</li>
        <li>Title:{title}</li>
        <li>Content: {findResult.content}</li>
      </ul>
    )
  }
}
 
3. 代码 - 跳转 + 携带 state 参数
 
3.1 Message
 
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Detail from "./Detail";
export default class Message extends Component {
  state = {
    messageArr: [
      { id: "01", title: "消息1" },
      { id: "02", title: "消息2" },
      { id: "03", title: "消息3" },
    ],
  };
  pushShow = (id, title) => {
    
    this.props.history.push(`/home/message/detail`, {id,title})
  }
  replaceShow = (id, title) => {
    
    this.props.history.replace(`/home/message/detail`, {id,title})
  }
  render() {
    const { messageArr } = this.state;
    return (
      <div>
        <ul>
          {messageArr.map((msgObj) => {
            return (
              <li key={msgObj.id}>
                {}
                <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id, title:msgObj.title}}}>{msgObj.title}</Link>
                 <button onClick={()=>this.pushShow(msgObj.id, msgObj.title)}>push查看</button>
                 <button onClick={()=>this.replaceShow(msgObj.id, msgObj.title)}>replace查看</button>
              </li>
            );
          })}
        </ul>
        <hr />
        {}
        <Route path="/home/message/detail" component={Detail} />
      </div>
    );
  }
}
 
3.2 Detail
 
import React, { Component } from 'react'
const Detaildata = [
    {id:'01', content:'你好,中国'},
    {id:'02', content:'你好,小帽学堂'},
    {id:'03', content:'你好,未来的自己'}
]
export default class Detail extends Component {
  render() {
    const {id, title} = this.props.location.state
    const findResult = Detaildata.find((detailObj)=>{
        return detailObj.id === id
    })
    return (
      <ul>
        <li>ID:{id}</li>
        <li>Title:{title}</li>
        <li>Content: {findResult.content}</li>
      </ul>
    )
  }
}
 
4. 代码 - 前进后退
 
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Detail from "./Detail";
export default class Message extends Component {
  state = {
    messageArr: [
      { id: "01", title: "消息1" },
      { id: "02", title: "消息2" },
      { id: "03", title: "消息3" },
    ],
  };
  pushShow = (id, title) => {
    
    this.props.history.push(`/home/message/detail`, { id, title });
  };
  replaceShow = (id, title) => {
    
    this.props.history.replace(`/home/message/detail`, { id, title });
  };
  back = () => {
    this.props.history.goBack();
  };
  forward = () => {
    this.props.history.goForward();
  };
  go = () => {
    this.props.history.go(-2);
  };
  render() {
    const { messageArr } = this.state;
    return (
      <div>
        <ul>
          {messageArr.map((msgObj) => {
            return (
              <li key={msgObj.id}>
                {}
                <Link
                  to={{
                    pathname: "/home/message/detail",
                    state: { id: msgObj.id, title: msgObj.title },
                  }}
                >
                  {msgObj.title}
                </Link>
                 
                <button onClick={() => this.pushShow(msgObj.id, msgObj.title)}>
                  push查看
                </button>
                 
                <button
                  onClick={() => this.replaceShow(msgObj.id, msgObj.title)}
                >
                  replace查看
                </button>
              </li>
            );
          })}
        </ul>
        <hr />
        {}
        <Route path="/home/message/detail" component={Detail} />
        <button onClick={this.back}>回退</button> 
        <button onClick={this.forward}>前进</button> 
        <button onClick={this.go}>go</button>
      </div>
    );
  }
}
 
5. 总结
 
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
	-this.prosp.history.push()
	-this.prosp.history.replace()
	-this.prosp.history.goBack()
	-this.prosp.history.goForward()
	-this.prosp.history.go()
 
6. withRouter 的使用
 
Header
 
import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'
class Header extends Component {
	back = ()=>{
		this.props.history.goBack()
	}
	forward = ()=>{
		this.props.history.goForward()
	}
	go = ()=>{
		this.props.history.go(-2)
	}
	render() {
		console.log('Header组件收到的props是',this.props);
		return (
			<div className="page-header">
				<h2>React Router Demo</h2>
				<button onClick={this.back}>回退</button> 
				<button onClick={this.forward}>前进</button> 
				<button onClick={this.go}>go</button>
			</div>
		)
	}
}
export default withRouter(Header)
 

 
七、BrowserRouter 与 HashRouter 的区别
 
1.底层原理不一样:
	BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
	HashRouter使用的是URL的哈希值。
2.path表现形式不一样
	BrowserRouter的路径中没有
	HashRouter的路径包含
3.刷新后对路由state参数的影响
	(1).BrowserRouter没有任何影响,因为state保存在history对象中。
	(2).HashRouter刷新后会导致路由state参数的丢失!!!
4.备注:HashRouter可以用于解决一些路径错误相关的问题。