官方文档----https://reacttraining.com/react-router/web/example/basic
react-router-dom
包npm install react-router-dom --save
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { BrowserRouter as Router, Route, Link, HashRouter } from "react-router-dom";
...
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</div>
</Router>
老浏览器提供的 hash模式, 我们称之为: HashRouter。H5提供的的 history 模式,我们称之为 BrowserRouter
注意:
HashRouter
和BrowserRouter
路由器必须要包裹住所有的路由组件
一般我们会在项目的入口文件index.js
中包裹项目的根组件App.js
,保证HashRouter
和BrowserRouter
可以包裹所有的路由组件。如下:
ReactDOM.render(
// 用路由器将项目根组件 App 包裹住,保证路由器正常包裹所有的路由组件
<HashRouter>
<App />
</HashRouter>,
document.getElementById('root')
);
route
组件表示配置一条路由。如下:
<Route path="/list" component={List} exact>Route>
其中:
path
:匹配路由component
:匹配路由后要展示的组件exact
:路由精准匹配Redirect
组件表示路由重定向。当页面匹配不到路由时,会使用重定向路由。如下:
<Redirect to="/home" />
注意:
Redirect
重定向路由一定要放在路由表的最后
Switch
组件包裹住的路由只匹配一次。如下:
<Switch>
<Route path = "/" component = {Home} exact>Route>
<Route path = "/home" component = {Home}>Route>
<Route path = "/mine" component = {Mine} >Route>
<Route path = "/mine/login" component = {Login} exact >Route>
<Redirect to="/home/page1" />
Switch>
当路由为 /mine
时,会匹配到/mine
路由,Mine
组件。之后就不会再进行匹配,也就是说,/mine/login
不会被匹配到,也就不会展示Login
组件。
Link
和NavLink
组件会被渲染为a
标签。如下:
<ul>
<li>
<NavLink activeClassName="active" to="/">HomeNavLink>
li>
<li>
<NavLink activeClassName="active" to="/about">AboutNavLink>
li>
<li>
<NavLink activeClassName="active" to="/about/aaa">DashboardNavLink>
li>
ul>
NavLink
组件在路由激活时可以用activeClassName
来添加active
类名。而Link
组件则没有。
<Demo/>
<Route path="/demo" component={Demo}/>
// 一般组件:写组件标签时传递了什么,就能收到什么
// 路由组件:接收到三个固定的属性 console.log(this.props)
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
pathname: "/about"
search: ""
state: undefined
match:
params: {}
path: "/about"
url: "/about"
<Route path="/content/:id" component={NewsContent}/>
// 新闻列表页
import React, { Component } from 'react';
import { Link } from "react-router-dom";
class News extends Component {
state = {
infos:[
{ aid:1, info:"河南" },
{ aid:2, info:"江苏" }
]
}
render() {
return (
<div>
{
this.state.infos.map((value,index)=>{
return <p key={value.aid}><Link to={`/content/${value.aid}`}>{value.info}</Link></p>
})
}
</div>
);
}
}
export default News;
之后在新闻详情页组件,可以通过this.props.match.params.aid
获取到参数
<Route path="/content" component={NewsContent}/>
import React, { Component } from 'react';
import { Link } from "react-router-dom";
class Pnews extends Component {
state = {
infos:[{ aid:1, info:"北京" },
{ aid:2, info:"上海" } ]
}
render() {
return (
<div>
{
this.state.infos.map((value,index)=>{
// 这里直接像 url 一样,在 url 后面以 search 的形式传参
return <p key={index}><Link to={`/pcontent?aid=${value.aid}`}>{value.info}</Link></p>
})
}
</div>
);
}
}
export default Pnews;
之后在新闻详情页组件,可以通过this.props.location.search
获取到参数
<Route path="/content" component={NewsContent}/>
详情Link>
console.log(this.props.location.state) // 接收参数
// 借助 this.prosp.history 对象上的 API 操作路由跳转、前进、后退
this.prosp.history.push(url) // 在路由栈中保留当前路由记录,并跳转到 url 路由
this.prosp.history.replace(url) // 不保留当前路由记录,跳转到 url 路由
this.prosp.history.goBack() // 回退
this.prosp.history.goForward()
this.prosp.history.go() // 前进
/****** APP.jsx ******/
import React, { Component } from 'react';
import './assets/css/App.css';
import Home from './components/Home.jsx';
import New from './components/New.jsx';
import { BrowserRouter as Router, Route,Link } from "react-router-dom";
import Info1 from './components/New/Info1.jsx';
import Info2 from './components/New/Info2.jsx';
// 配置路由,甚至可以把它单独提出一个js的文件
let routes=[
{
path:'/',
component:Home,
exact:true
},
{
path:'/new',
component:New,
routechilden:[
{
path:'/new/',
component:Info1
},
{
path:'/new/info',
component:Info2
}
]
}
]
class App extends Component {
render() {
return (
<Router>
<div>
<Link to='/new'>新闻页面</Link>
{/* 不需要配置嵌套路由的写法
{
routes.map((route,index)=>{
if(route.exact){
return
}else{
return
}
})
} */ }
{/* 需要配置嵌套路由的写法
以下写法是基本上的固定写法,因为组件传参的方式在路由
中无效,所以下面适用于子路由存在的情况下
但是下面childroutes这个是可以自定义,但是不能是
childerns(可能内部已经使用)
*/}
{
routes.map((route,index)=>{
if(route.exact){
return <Route exact key={index} path={route.path} render={
props=>(
<route.component {...props} childroutes={route.routechilden}/>
)
}/>
}else{
return <Route key={index} path={route.path} render={
props=>(
<route.component {...props} childroutes={route.routechilden}/>
)
}/>
}
})
}
</div>
</Router>
);
}
}
export default App;