React-Router.v4学习笔记

在web下我们一般都使用react-router-dom,相比于react-router多了一些DOM操作方法,你可以尝试单独安装react-router-dom,看依赖包里面是不是会包含了react-router,本文就记录下react-router-dom一些笔记(文章中api示例只给出了常用,详细api请查看官方文档)

安装

npm install react-router-dom

基本使用

import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
const Router = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route path='/' exact component={AsyncHome}/>
                <Route path='/hot' exact component={AsyncHot}/>
            </Switch>
        </BrowserRouter>
    )
}
export default Router

// 然后在App.js
import Router from './router';
const App = () => {
    render(){
        return (
            <React.Fragment>
                <Header/>
                {router}
            </React.Fragment>
        )
    }
}
export default App
//最后在inde中引用App即可

基本组件

React-Router中有三种类型的组件:路由器组件,路由匹配组件和导航组件

路由器组件

react-router-dom提供<BrowserRouter><HashRouter>路由器

  • <BrowserRouter>
    原理是使用HTML5 history API,内容随着url动态改变
  • <HashRouter>
    有是根据hash值对路由进行控制的(会有#)

举个例子:

import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

路由匹配组件

有两个路由匹配组件:<Route><Switch>

  • <Route>:Route是路由的一个原材料,它是控制路径对应显示的组件。经常用的是exact、path以及component属性
    exact:控制匹配到/路径时不会再继续向下匹
    path:路由的路径
    component:显示组件
  • <Switch>:Switch常常会用来包裹Route,它里面不能放其他元素,用来只显示一个路由。

举个例子:

<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Route path="/contact" component={Contact} />
</Switch>

API:

名称 示例 属性 作用
path /users/:id string 定义路径
exact exact path=”/one” bool 严格匹配

导航组件

<Link><NavLink>一般在组件内跳转链接用的

  • <Link><Link to="/home"> to可以接收一个string和object
  • <NavLink>:可以为当前选中的路由设置类名、样式以及回调函数等

举个例子:

<Link
  to={{
    pathname: "/courses",
    search: "?sort=name",
    hash: "#the-hash",
    state: { fromDashboard: true }
  }}
/>

<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: "bold",
    color: "red"
  }}
>
  FAQs
</NavLink>

API:

<Link>

名称 示例 属性 作用
to to=”/home” string 跳转路径
exact exact to=”/one” bool 严格匹配

<NavLink>

名称 示例 属性 作用
to to=”/home” string 跳转路径
exact exact to=”/one” bool 严格匹配
activeClassName activeClassName=’active’ bool 当前路径选中状态的类名

代码拆分

其实就是按需加载,不管是官方还是用户,都有给出自己的方式,这里给出官方的示例代码,在我看来还是挺简单的!

create-react-app

npm install @babel/plugin-syntax-dynamic-import
//router>index.js
import Loadable from "react-loadable";
import Loading from "./Loading";
const Home = Loadable({
  loader: () => import("./home"),
  loading: Loading//必须配置loading组件,不然报错
});
const Router = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route path='/' exact component={Home}/>
            </Switch>
        </BrowserRouter>
    )
}
export default Router

更多按需加载的方法请参考:https://segmentfault.com/a/1190000009539836

重定向

使用<Redirect>可以重定向路径

import { Route, Redirect } from 'react-router'
//to是string的时候
<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>
//进入首页,判断是否已登陆,如果登陆重定向到用户面板
//当to是object的时候
<Redirect
  to={{
    pathname: "/login",
    search: "?utm=your+face",
    state: { referrer: currentLocation }
  }}
/>

match

match是在使用router之后被放入props中的一个属性(/home/:id)
match对象包含以下属性:

  • params – (对象)从与路径的动态段对应的URL解析的键/值对
  • isExact- (boolean)是否是严格模式
  • path – (字符串)用于匹配的路径模式。
  • url – (字符串)URL的匹配部分。

withRouter

使用过vue-router的同学可能刚开始会很奇怪,为什么react-router没有直接在组件中js跳转路由的方法,比如this.$router.push

withRouter:是一个可以让你访问history对象的属性和最近<Route>match的高阶组件

利用withRouter达到路由js跳转

import React from "react";
import {withRouter } from 'react-router-dom';

class TLogin extends React.Component {

    handleJump(){//在方法内调用
        this.props.history.push('/home)
    }

    render() {
        //dosomething
  }
}
const Login = withRouter(TLogin)
export default Login;

//使用react-redux的时候
onst Login = withRouter(connect(...)(TLogin))
export default Login;

路由嵌套

v4中不支持以前这种写法

    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>

v4中子路由,应写在对应的组件内部中,当然你可以用react-router-config对象的方式配置嵌套,和vue-router一样的。

npm install --save react-router-config

//app.js import {renderRoutes} from 'react-router-config'; import Router from './router'; const App = () => { render(){ return ( <React.Fragment> <Header/> {renderRoutes(Router)} </React.Fragment> ) } } export default App //./router export const Router = [ { component: home, path:'/', },{ component:parent, path:'/parent', routes: [ { path: "/parent/:id", component: Child, routes: [ { path: "/parent/:id/grand-child", component: GrandChild } ] } ] } ];

异步加载组件

1.新建AsyncComponents组件


import React, {Component} from 'react'; export default function asyncComponents(importComponent) { class AsyncComponent extends Component { constructor(props) { super(props); this.state = { component: null, } } async componentDidMount() {//异步 const {default: component} = await importComponent(); this.setState({ component: component }); } render() { const C = this.state.component; return C ? <C {...this.props} /> : null; } } return AsyncComponent }

2、在router>index.js

import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import asyncComponents from  "../components/AsyncComponents"

const AsyncHome = asyncComponents(() => import('../page/home/home'));
const AsyncHot = asyncComponents(() => import('../page/hot/hot'));

const router = (
    <BrowserRouter>
        <Switch>
            <Route path='/' exact component={AsyncHome}/>
            <Route path='/hot' exact component={AsyncHot}/>
        </Switch>
    </BrowserRouter>
);
export default router

这种异步加载组件的方案和官方推荐的按需加载效果和速度、性能基本上差不多!