react-router-dom
1、react的一个插件,专门用来实现单页面。
2、基于react的项目基本都会用到它。
路由的基本使用
1、路由导航区标签为Link或NavLink标签
<Link to="/xxx">xxx</Link>
<NavLink to="/xxx">xxx</NavLink>
NavLink标签会为当前匹配路由添加"active"类名,我们可以通过activeClassName来更改它的默认类名
tips:所有组件体的内容可以通过this.props.children获取,如果标签属性children也是可以通过 this.props.children获取。
eg: <NavLink to="/xxx">xxx</NavLink>等同于<NavLink to="/xxx" children="xxx" />
2、路由展示区写Route标签进行路径匹配
<Route path="/xxx" component={xxx}>
3、App外侧包裹一个<BrowserRouter> 或 <HashRouter>
import './App.css';
import Hello from "./component/hello/index"
import Bea from "./component/bea/index"
import { Link,NavLink, BrowserRouter, Route } from "react-router-dom";
function App() {
return (
<div className="App">
{/* 需要包裹路由,需要包裹在最外层,最好的做法是直接包裹App组件 */}
<BrowserRouter>
<p>react router!</p>
{/* <Hello name='deng'/>
<Bea /> */}
<div className='list'>
{/* <Link className='item-link' to="/bea">bea组件</Link>
<Link className='item-link' to="/hello">hello组件</Link> */}
<NavLink className='item-link' activeClassName='routeActive' to="/bea">bea组件</NavLink>
<NavLink className='item-link' activeClassName='routeActive' to="/hello">hello组件</NavLink>
</div>
<div className='show-area'>
{/* 注册路由 */}
<Route path="/bea" component={Bea}></Route>
<Route path="/hello" component={Hello}></Route>
</div>
</BrowserRouter>
</div>
);
}
export default App;
路由组件和一般组件
1.写法不同
一般组件:<Demo />
路由组件:<Route path="/demo" component={Demo} />
2.存放位置不同
一般组件:components
路由组件:pages
3.接收到的props不同
一般组件:写组件标签时传递了什么,就能接收到什么
路由组件:接收到三个固定的属性history location match
switch的使用
当写了多个相同的路由时,react会将路由对应的组件全部显示出来。可以用switch包裹路由,这样react匹配到一个路由后就不会再继续匹配了。
不使用switch时:
使用switch时:
import './App.css';
import Hello from "./component/hello/index"
import Bea from "./component/bea/index"
import { Link, NavLink, Switch, BrowserRouter, Route } from "react-router-dom";
function App() {
return (
<div className="App">
{/* 需要包裹路由,需要包裹在最外层,最好的做法是直接包裹App组件 */}
<BrowserRouter>
<p>react router!</p>
{/* <Hello name='deng'/>
<Bea /> */}
<div className='list'>
{/* <Link className='item-link' to="/bea">bea组件</Link>
<Link className='item-link' to="/hello">hello组件</Link> */}
<NavLink className='item-link' activeClassName='routeActive' to="/bea">bea组件</NavLink>
<NavLink className='item-link' activeClassName='routeActive' to="/hello">hello组件</NavLink>
</div>
<div className='show-area'>
{/* 注册路由 */}
<Switch>
<Route path="/bea" component={Bea}></Route>
<Route path="/hello" component={Hello}></Route>
<Route path="/hello" component={Hello}></Route>
</Switch>
</div>
</BrowserRouter>
</div>
);
}
export default App;
路由的严格匹配和模糊匹配
react路由匹配默认为模糊匹配,即/bea/a是能匹配到/bea的,但是/a/bea无法匹配到/bea,需要满足最左匹配。
设置exact为true可开启严格匹配
<Route exact path="/bea" component={Bea}></Route>
注意:严格匹配模式不要随便开启,需要再开,因为有时候开启可能会导致无法匹配二级路由。
Redirect的使用
Redirect组件需要放在注册路由的最底部,表示路由未匹配到时,跳转到指定的路由。
import './App.css';
import Hello from "./component/hello/index"
import Bea from "./component/bea/index"
import { Link, NavLink, Switch, BrowserRouter, Route, Redirect } from "react-router-dom";
function App() {
return (
<div className="App">
{/* 需要包裹路由,需要包裹在最外层,最好的做法是直接包裹App组件 */}
<BrowserRouter>
<p>react router!</p>
<div className='row'>
<div className="col-md-4 row-item">.col-md-4</div>
<div className="col-md-4 row-item">.col-md-4</div>
<div className="col-md-4 row-item">.col-md-4</div>
</div>
{/* <Hello name='deng'/>
<Bea /> */}
<div className='list'>
{/* <Link className='item-link' to="/bea">bea组件</Link>
<Link className='item-link' to="/hello">hello组件</Link> */}
<NavLink className='item-link' activeClassName='routeActive' to="/a/bea">bea组件</NavLink>
<NavLink className='item-link' activeClassName='routeActive' to="/a/hello">hello组件</NavLink>
</div>
<div className='show-area'>
{/* 注册路由 */}
<Switch>
<Route path="/a/bea" component={Bea}></Route>
<Route path="/a/hello" component={Hello}></Route>
<Route path="/a/hello" component={Hello}></Route>
<Redirect to="/a/bea" />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
export default App;
嵌套路由
1、注册子路由时要加上父路由path值
2、路由的匹配是按照注册路由的顺序进行的
向路由组件传递参数
方法一:传递params参数
在跳转路由(Link、NavLink)路径后面,以路径的格式传递params参数,然后在路由展示组件(Route)path属性中通过“/:xxx”的形式申明要接收的params参收。这样在路由对应的组件内就可以props.match.params中传递的路由参数了。
import React, { Component } from "react";
import Details from './details/index';
import { Link, Route } from 'react-router-dom';
export default class Message extends Component {
state = {
messageList: [
{ id: 1, name: '消息1:江西加油!' },
{ id: 2, name: '消息2:广东加油!' },
{ id: 3, name: '消息3:江苏加油!' },
]
};
render() {
const { messageList } = this.state;
return (
<div>
{
messageList.map(ele => {
return <p style={{
textAlign: 'left'
}} key={ele.id}>
{/* 向路由组件传递参数 */}
<Link to={`/hello/message/detail/${ele.id}/${ele.name}`}>{ele.name}</Link>
</p>
})
}
{/* 申明接收参数 */}
<Route path='/hello/message/detail/:id/:name' component={Details}></Route >
</div>
)
}
}
import React, { Component } from 'react'
const messageList = [
{ id: 1, content: '明天会更好!' },
{ id: 2, content: '我相信我就是我!' },
{ id: 3, content: '你可以的!' },
]
export default class Details extends Component {
render() {
//接收路由传递的参数
const { id, name } = this.props.match.params;
const content = messageList.find(ele => {
return ele.id == id;
})
return (
<div>
<p>ID: {id}</p>
<p>{name}</p>
<p>内容:{content.content}</p>
</div>
)
}
}
方法二:传递search参数
通过在Link或者NavLink组件中以urlencode的方式传递参数,这样在路由对应的组件内就可以props.location.search中接收传递的路由参数了。
import React, { Component } from "react";
import Details from './details/index';
import { Link, Route } from 'react-router-dom';
export default class Message extends Component {
state = {
messageList: [
{ id: 1, name: '消息1:江西加油!' },
{ id: 2, name: '消息2:广东加油!' },
{ id: 3, name: '消息3:江苏加油!' },
]
};
render() {
const { messageList } = this.state;
return (
<div>
{
messageList.map(ele => {
return <p style={{
textAlign: 'left'
}} key={ele.id}>
{/* 向路由组件传递search参数 */}
<Link to={`/hello/message/detail?id=${ele.id}&name=${ele.name}`}>{ele.name}</Link>
</p>
})
}
{/* search无需申明接收 */}
<Route path='/hello/message/detail' component={Details}></Route >
</div>
)
}
}
获取到的search参数是未解析好的,可以用react已经下好的qs模块来解析urlencode编码字符串
import React, { Component } from 'react'
import qs from "qs";
const messageList = [
{ id: 1, content: '明天会更好!' },
{ id: 2, content: '我相信我就是我!' },
{ id: 3, content: '你可以的!' },
]
export default class Details extends Component {
render() {
//接收路由search参数
const searchStr = this.props.location.search;
const search = qs.parse(searchStr.slice(1));
const content = messageList.find(ele => {
return ele.id == search.id;
})
return (
<div>
<p>ID: {search.id}</p>
<p>{search.name}</p>
<p>内容:{content.content}</p>
</div>
)
}
}
方法三:传递state参数
通过在Link或者NavLink组件中,to传递一个对象,pathname属性为跳转路径,state为传递的路由参数
import React, { Component } from "react";
import Details from './details/index';
import { Link, Route } from 'react-router-dom';
export default class Message extends Component {
state = {
messageList: [
{ id: 1, name: '消息1:江西加油!' },
{ id: 2, name: '消息2:广东加油!' },
{ id: 3, name: '消息3:江苏加油!' },
]
};
render() {
const { messageList } = this.state;
return (
<div>
{
messageList.map(ele => {
return <p style={{
textAlign: 'left'
}} key={ele.id}>
{/* 向路由组件传递state参数 */}
<Link to={{ pathname: `/hello/message/detail`, state: { id: ele.id, name: ele.name } }}>{ele.name}</Link>
</p>
})
}
{/* state无需申明接收 */}
<Route path='/hello/message/detail' component={Details}></Route >
</div>
)
}
}
通过props.location.state接收传递的参数
import React, { Component } from 'react'
import qs from "qs";
const messageList = [
{ id: 1, content: '明天会更好!' },
{ id: 2, content: '我相信我就是我!' },
{ id: 3, content: '你可以的!' },
]
export default class Details extends Component {
render() {
//接收路由state参数
const state = this.props.location.state;
const content = messageList.find(ele => {
return ele.id == state.id;
})
return (
<div>
<p>ID: {state.id}</p>
<p>{state.name}</p>
<p>内容:{content.content}</p>
</div>
)
}
}