环境介绍
当前使用的版本为:
"react-router-dom": "^4.3.1"
react-router 与 react-router-dom
可以认为react-router 为 react-router-dom 的子集
比如以下写法:
import { HashHistory, Switch, Route, Router, Link } from 'react-router-dom'
// 等价于
import { Switch, Route, Router } from 'react-router'
import { HashHistory, Link } from 'react-router-dom'
react-router 实现了路由的核心功能。 react-router-dom 是基于react-router,加入了浏览器操作的一些功能。所以只需要下载依赖react-router-dom就可以了。以下是记录react-router-dom的简单使用。
Link 与 NavLink
Link 的用法
import { Link } from 'react-router-dom'
<Link to='/about'></Link>
<Link
to={{
pathname:'/about',
search: "?sort=name",
hash: "#the-hash",
state: { fromDashboard: true }
}} />
<Link to='/about' replace />
//用过vue的,对这个比较清楚,添加这个不会把该路由添加到访问的历史记录里。
pathname: (string)路由名称。
search:(string)查询参数的字符串表示形式。
hash:添加hash值到url里,可对应路由。
state: 在路由里添加含有状态的变量,根据变量,来对路由做相应的处理。
NavLink
<Link /> 组件里的特殊组件。当前url匹配时,为该元素添加样式属性。比如table切换的时候,选中的一栏字体高亮等。
import { NavLink } from 'react-router-dom'
<NavLink to="/about">About</NavLink> // 一般用法
<NavLink to="/about" activeClassName="selected">About</NavLink> // 添加激活的时的class
<NavLink
to="/about"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
About
</NavLink>
// 可以直接添加样式
Redirect
重定向重新加载页面。
import { Route, Redirect } from 'react-router'
// 如果未登录,重定向登录界面
<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/loggedIn" />
) : (
<HomePage/>
)
)}/>
// to: string
<Redirect to="/list/id" />
// to: Object
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
// from: string
<Redirect from='/old-path' to='/new-path'/>
<Redirect from='/users/:id' to='/users/profile/:id'/>
这边简单实现比较常用的table切换,用到的重定向的问题。下面实现当从一个页面跳转到一个table切换的页面,默认重定向已通过的模块(也可以定向到其他页面,根据自己需求,设置type值。这里需要注意的一点是,如果当前页面是首页的话,就不能使用this.props.match.path, 因为路由match对象还不存在,如果想在首页实现的话,就不要加this.props.match.path)。
import React from 'react';
import { NavLink, Switch, Route, Redirect } from 'react-router-dom';
class App extends React.Component {
render(){
return(
<div>
<NavLink to={`${this.props.match.path}/passed`} className="nav-link">已通过</NavLink>
<NavLink to={`${this.props.match.path}/audited`} className="nav-link">待审核</NavLink>
<NavLink to={`${this.props.match.path}/failed`} className="nav-link">未通过</NavLink>
<!--子路由在父级配置-->
<Switch>
<Route path={`${this.props.match.path}/:type`} component={Content} />
<Redirect from={`${this.props.match.path}`} to={`${this.props.match.path}/passed`} exact component={Content} />
</Switch>
</div>
)
}
}
Route
是最基本的组件,当url匹配时,渲染对应的组件。
import { Router, Route } from 'react-router-dom';
<Router>
<Route exact path="/" component={Home} />
</Router>
// 获取传递的参数
<Route path="/user/:username" component={User} />;
function User({ match }) {
return <h1>Hello {match.params.username}!</h1>;
}
// 或者可以这样
class User extends Component{
constructor(props){
super(props)
}
render(){
return <h1>Hello { this.props.match.params.username}!</h1>;
}
}
这边还有route 路由渲染函数式表达,来处理过度动画,点击这里
Router
路由器的初级出口
常用的几种方式
import { BrowserRouter as Router } from 'react-router';
import { HashRouter as Router } from 'react-router';
import { Router } from 'react-router';
import createBrowserHistory from "history/createBrowserHistory";
const history = createBrowserHistory()
<Router history={history}>
<App/>
</Router>
Switch
常用来包裹<Route /> 和<Redirect /> 组件;
withRouter
顾名思义,是来关联路由。下面有使用到,也可以和react-redux一起使用,这里只介绍react-router部分。
react-router-dom 的简单的使用
这里我们实现两个路由跳转的案例来介绍路由的使用
- 比较常见的页面之间的跳转
我们先实现基本的骨架
<!--// app.js-->
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
class App extends Component {
nextPage = () => {
this.props.history.push('/test')
}
render(){
return (
<div>
<ul>
<li><NavLink to='/about'> About </NavLink></li>
<li><NavLink to='/inbox'> Inbox </NavLink></li>
</ul>
<div onClick={ this.nextPage }>测试<div>
</div>
)
}
}
// about.js
import React from 'react'
const About = () => {
return <h2>About</h2>
}
export default About;
//inbox.js
import React from 'react'
const Inbox = () => {
return <h2>Inbox</h2>
}
export default Inbox;
// test.js
import React from 'react'
const Test = () => {
return <h2>这是个测试</h2>
}
export default Test;
// router.js
import React from 'react'
import { BrowserRouter, Switch, Route } from 'react-router-dom'
import App from './App'
import About from './about'
import Inbox from './Inbox'
import Test from './test'
class Routes extends React.Component {
render(){
return (
<BrowserRouter>
<Switch>
<Route path='/' exact component={App}/> // exact 是精确匹配,如果没有这个,会匹配所有带有/的路由
<Route path='/about' component={About}/>
<Route path='/inbox' component={Inbox}/>
<Route path='/test' exact component={Test}/>
</Switch>
</BrowserRouter>
)
}
}
export default Routes;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Routes from './router'
ReactDOM.render(<Routes />, document.getElementById('root'));
- 这里render函数return的对象,必须要有一个跟标签,来包裹内容。如果不想要根标签,react还提供了<Fragment />组件来包裹内容。这里需要注意的是,还是需要提供的<Fragment /> 包裹内容,并且需要引入(和Component一样)。
-
实现页面内的内容切换
这里我们只需要对两个文件改动就可以了。一个是App.js, 一个是router.js。其他页面我们不动。
// App.js 修改为:
class App extends Component {
nextPage = () => {
this.props.history.push('/test')
}
render(){
return (
<div>
<ul>
<li><NavLink to='/about'> About </NavLink></li>
<li><NavLink to='/inbox'> Inbox </NavLink></li>
</ul>
<div onClick={ this.nextPage }>测试<div>
{ this.props.children }
</div>
)
}
}
// router.js修改为:
class Routes extends React.Component {
render(){
return (
<BrowserRouter>
<Switch>
<App>
<Route path='/about' component={About}/>
<Route path='/inbox' component={Inbox}/>
</App>
<Route path='/test' exact component={Test}/>
</Switch>
</BrowserRouter>
)
}
}
这里我们基本就是实现了页面内组件内容的切换了,但是此时出现了一个问题,当我点击‘测试’ 的时候,页面报错了。报错内容为“ TypeError: Cannot read property 'push' of undefined ” ,可以看出路由并没有匹配到,得到的是一个undefind。因为该组件没有关联到路由,这里需要(react-router-dom中的withRouter组件)关联下。
import React, { Component } from 'react'
import { NavLink, withRouter } from 'react-router-dom'
class App extends Component {
nextPage = () => {
this.props.history.push('/test');
}
render() {
return (
<div>
<ul>
<li><NavLink to="/about"> About </NavLink> </li>
<li><NavLink to="/inbox"> Inbox </NavLink></li>
</ul>
<div onClick={this.nextPage} >测试</div>
{ this.props.children }
</div>
);
}
}
export default withRouter(App);
但是还是没有跳转,额...
这边看下路由,尝试调整路由的位置
class Routes extends React.Component {
render(){
return (
<BrowserRouter>
<Switch>
<Route path='/test' exact component={Test}/>
<App>
<Route path='/about' component={About}/>
<Route path='/inbox' component={Inbox}/>
</App>
</Switch>
</BrowserRouter>
)
}
}
嗯,搞定。在当前页面切换不同组件内容,并实现页面间的路由跳转。
这里只是简单的使用react-router实现两种跳转方式,使用js控制路由的跳转,以及不同组件的使用,这里还有BrowserRouter 、HashRouter、StaticRouter、location、match、matchPath等。react-router还有很多强大的功能,这里只是用了基础的,后续会慢慢记录学习react以及相关插件。
具体参考官方文档, 因为网上有很多不同版本的介绍,感觉很乱,还是应该先查阅官方文档,如果不明白的地方,在具体查阅网上介绍,注意版本的区别。
如有不正确的地方,还请大佬斧正。