1.安装react-router-dom
webpack的安装命令:
cnpm i react-router-dom
2.使用react-router-dom
- 导入react,react-dom,react-router-dom
import React from 'react'
import ReactDOM from 'react-dom'
import {HashRouter as Router ,Link ,Route} from 'react-router-dom'
//import {BrowserRouter as Router,Link,Route} from 'react-router-dom'
- 定义子组件
function Login(){
return(<div>
<p>登陆</p>
</div>
)
}
function Registry(){
return(<div>
<p>注册</p>
</div>
)
}
- 定义父组件
class RouterT extends React.Component{
constructor(){
super()
this.state={
}
}
render(){
return (
<div>
<Router>
<Link to="/"></Link>
{/**加多一个空路径作为默认显示的组件*/}
<Link to="/login">登陆</Link>
<Link to="/registry">注册</Link>
<Route exact path="/" component={Login}/>
<Route path="/login" exact component={Login}></Route>
<Route path="/registry" component={Registry}></Route>
</Router>
</div>
)
}
}
这里使用Router是因为在导入react-router-dom时,给HashRouter起了别名,Route的component属性的值是一个组件类
- 将父组件渲染到页面
ReactDOM.render(
<RouterT></RouterT>
,document.getElementById('app')
)
使用HashRouter的话,网络地址就会加上#号,而使用BrowserRouter则不会,除此之外两者只有导入包的不同
Router标签的属性
- basename
作用:给Router下的link标签加上一个基本的根路径,用来防止路由之间的相互影响(在HashRouter中存在影响,使用BrowserRouter比较好)
使用:
<Router basename="/根路径"></Router>
注意:这个属性用处不大,有些bug,在使用HashRouter时,仍会存在影响,没加这个属性的仍会影响到其他路由
Link标签的属性
- to
作用:给link标签一个路由路径,用来指向route
使用:
<Link to="/路由路径"></Link>
其他使用方法:
可以给to属性传递一个对象,这样可以实现传参
<Link to={{pathname:"/路由路径",search:'?参数名称=参数值',hash:'#一个哈希值',state:{数据名称:'数据'}}}>点击</Link>
只有使用class创建的组件才能访问到这个对象,使用this.props.location就可以访问
- replace
作用:将点击触发的路由替换掉已经打开的路由的历史记录地址的缓存
在后退时,不会再经过刚刚打开的路由
使用:
<Link to="/路由路径" replace></Link>
Redirect标签
作用:实现路由的重定向
使用:
- 导入Redirect标签
import React from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter as Router,Link,Route,Redirect} from 'react-router-dom'
- 定义一个组件
class RedirectTest extends React.Component{
render(){
if(this.props.msg)return (
<Redirect to="/路由路径1"></Redirect>
)
else return(
<Redirect to="/路由路径2"></Redirect>
)
}
}
3.将组件渲染到页面
ReactDOM.render(<div>
<Router>
<RedirectTest msg={true}></RedirectTest>
<Route path="/路由路径1" component={()=>{return<h1>aaaa</h1>}}></Route>
<Route path="/路由路径2" component={()=>{return<h1>bbbb</h1>}}></Route>
</Router>
</div>
,document.getElementById('app')
)
Redirect标签相当于一个强制跳转,一旦有这个标签,就一定要跳转到它所带的路由路径上去,所以一般只适用于做判断组件
Switch标签
作用:实现路由的匹配不会重复,只要有一个匹配到了,其他的就不会被匹配到
如果是要在几个路由之间只匹配一个,就必须加上这个标签,因为路由的匹配不会因为匹配到了,就停止匹配了
使用:
- 导入Switch标签
import {BrowserRouter as Router,Link,Route,Switch} from 'react-router-dom'
- 用Switch标签包裹Route标签
<Switch>
<Route path="/路由路径1" component={()=>{return<h1>aaaa</h1>}}></Route>
<Route path="/路由路径2" component={()=>{return<h1>bbbb</h1>}}></Route>
</Switch>
3.路由传值
方式一
- 导入react,react-dom,react-router-dom
import React from 'react'
import ReactDOM from 'react-dom'
import {HashRouter as Router ,Link ,Route} from 'react-router-dom'
//import {BrowserRouter as Router,Link,Route} from 'react-router-dom'
- 定义子组件
function Login(props){
console.log(props.match.params.id)
return(<div>
<p>登陆</p>
</div>
)
}
- 定义父组件
class RouterT extends React.Component{
constructor(){
super()
this.state={
}
}
render(){
return (
<div>
<Router>
<Link to="/"></Link>
{/**加多一个空路径作为默认显示的组件*/}
<Link to="/login/123465">登陆</Link>
<Link to="/registry">注册</Link>
<Route exact path="/" component={Login}/>
<Route path="/login/:id" exact component={Login}></Route>
{/**这里的id是一个占位符,需要提前写,才能使用这个id接受数据*/}
<Route path="/registry" component={Registry}></Route>
</Router>
</div>
)
}
}
- 将父组件渲染到页面
ReactDOM.render(
<RouterT></RouterT>
,document.getElementById('app')
)
在点击登陆时,就会将/login/后面的字符串传递到props下的match,params中
在class创建的组件中,不用加个接收参数props,直接使用this.props就可以获取match,params
方式二
- 导入react,react-dom,react-router-dom
import React from 'react'
import ReactDOM from 'react-dom'
import {HashRouter as Router ,Link ,Route} from 'react-router-dom'
//import {BrowserRouter as Router,Link,Route} from 'react-router-dom'
- 定义组件
class MyButton extends React.Component{
render(){
return (<div>
<button onClick={this.click}>点击</button>
</div>
)
}
click=()=>{
console.log(this.props)
this.props.history.push("/路由路径",{msg:'MyButton传递过来的数据'})
}
}
- 将组件渲染到页面
ReactDOM.render(<div>
<Router>
<Route path="/" component={MyButton}></Route>
<Route path="/路由路径" component={(props)=>{
return<h1>{props.location.state.msg}</h1>
}}></Route>
</Router>
</div>
,document.getElementById('app')
)
通过this.props.history.push("/路由路径",{数据名称:‘数据’})这种方式传递的数据,会存放在props.location.state中,class创建出来的组件就不用接收参数,直接用this.props.location.state接收即可
这里有一个主意事项:
在使用BrowserRouter时,才能向this.props.history中push数据(state)
但有一个缺陷,就是如果想直接通过地址访问非根路由的话,就会发起请求,只能使用页面内的link或this.props.history进行路由跳转
在使用HashRouter时,就能够访问非跟路由,而不发起请求
当使用向this.props.history中push数据(state)时,会报以下的错误
Warning: Hash history cannot push state; it is ignored
这说明HashRouter不能使用这种方式传递数据,
在Vue中可以使用HashRouter传递数据
props.history的其他方法
//也是跳转,跟push方法差不多
//只不过它在跳转后,不会保留上一个页面的历史记录地址的缓存
props.history.replace("/",{数据名称:'数据'})
//前进
props.history.go(1)
props.history.goForward()
//后退
props.history.go(-1)
props.history.goBack()