美文网首页
初识react-router

初识react-router

作者: 刈懋 | 来源:发表于2019-01-31 23:52 被阅读2次

环境介绍

当前使用的版本为:

"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 的简单的使用

这里我们实现两个路由跳转的案例来介绍路由的使用

  • 比较常见的页面之间的跳转
image

我们先实现基本的骨架

<!--// 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一样)。
  • 实现页面内的内容切换


    image

这里我们只需要对两个文件改动就可以了。一个是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 HashRouterStaticRouterlocationmatchmatchPath等。react-router还有很多强大的功能,这里只是用了基础的,后续会慢慢记录学习react以及相关插件。

具体参考官方文档, 因为网上有很多不同版本的介绍,感觉很乱,还是应该先查阅官方文档,如果不明白的地方,在具体查阅网上介绍,注意版本的区别。

如有不正确的地方,还请大佬斧正。

相关文章

网友评论

      本文标题:初识react-router

      本文链接:https://www.haomeiwen.com/subject/skkrsqtx.html