阅读 2796

react-router4入门教程

npm包的区别

首先从react-router的npm包开始看起,分别有react-router和react-router-dom,两者的区别在于后者具有一些dom api,比如Link、BrowserRouter、HashRouter。不难发现react-router-dom具有一些在浏览器上所需要的api,而react-router只有核心api,所以我们总结下

  • react-router 路由核心功能包
  • react-router-dom 在浏览器上使用的react路由
  • react-router-native 在app上使用的react路由

其中react-router-dom和react-router-native都继承自react-router,所以我们在浏览器上开发只需要引入react-router-dom即可

react-router-dom api详解

我最先接触的框架是vue,vue中的路由配置使用的是配置文件,而react使用的是jsx来配置路由,所以初次学习会有点别扭。

HashRouter和BrowserRouter

其实就是路由的hash和history两种模式(要是不了解这两种模式之间的区别那就需要去恶补下啦)
并且这两个组件是路由的容器,必须在最外层

// hash模式
ReactDom.render(
	<HashRouter>
      	<Route path="/" component={Home}/>
    </HashRouter>
)

// history模式
ReactDom.render(
	<BrowserRouter>
      	<Route path="/" component={Home}/>
    </BrowserRouter>
)
复制代码

下面说说HashRouter和BrowserRouter上的参数

  • basename 路由的基础链接,用来部署到非根目录下,比如你需要将项目部署到 www.xxxx.com/web 下,则设置basename="/web"
  • getUserConfirmation 用来拦截Prompt组件,并且决定是否跳转
  • forceRefresh 用来设置是否强制浏览器整体刷新,默认值为false
  • keLength 用来设置location.key的长度,默认是6,可以自定义

Prompt

Prompt是用来提示用户是否要跳转,给用户提示信息默认使用window.confirm,可以结合getUserConfirmation构建自定义提示信息

<Prompt message={location => {
    return '请确认'
}}/>

如果直接返回true,则不会弹窗
复制代码

Route

Route是路由的一个原材料,它是控制路径对应显示的组件

Route的参数

  • path 跳转的路径
  • component 对应路径显示的组件
  • render 可以自己写render函数返回具体的dom,而不需要去设置component
  • location 传递route对象,和当前的route对象对比,如果匹配则跳转
  • exact 匹配规则,true的时候则精确匹配。
path url 是否开启 匹配结果
/a /a/b false yes
/a /a/b true no
  • sensitive 是否区分path的大小写
path url 是否开启 匹配结果
/a /a true yes
/a /A true yes
  • strict 是否匹配后面的/
path url 是否开启 匹配结果
/a /a/ true yes
/a /a/c true yes
/a /a true no

Router

低级路由,适用于任何路由组件,主要和redux深度集成,使用必须配合history对象
使用Router路由的目的是和状态管理库如redux中的history同步对接

<Router history={history}>
    ...
</Router>
复制代码

Link和NavLink

两者都是跳转路由,NavLink的参数更多些

Link的api

  • to 有两种写法,表示跳转到哪个路由
    • 字符串写法
      <Link to="/a"/>
      复制代码
    • 对象写法
      <Link to={{
        pathname: '/courses',
        search: '?sort=name',
        hash: '#the-hash',
        state: { fromDashboard: true }
      }}/>
      复制代码
  • replace 就是将push改成replace
  • innerRef 访问Link标签的dom

NavLink的api

  • Link的所有api
  • activeClassName 路由激活的时候设置的类名
  • activeStyle 路由激活设置的样式
  • exact  参考Route,符合这个条件才会激活active类
  • strict  参考Route,符合这个条件才会激活active类
  • isActive 接收一个回调函数,active状态变化的时候回触发,返回false则中断跳转
const oddEvent = (match, location) => {
  console.log(match,location)
  if (!match) {
    return false
  }
  console.log(match.id)
  return true
}
<NavLink isActive={oddEvent} to="/a/123">组件一</NavLink>
复制代码
  • location 接收一个location对象,当url满足这个对象的条件才会跳转
<NavLink to="/a/123" location={{ key:"mb5wu3", pathname:"/a/123" }}/>
复制代码

Redirect

Redirect重定向很简单,我们直接看代码即可

// 基本的重定向
<Redirect to="/somewhere/else" />

// 对象形式
<Redirect
  to={{
    pathname: "/login",
    search: "?utm=your+face",
    state: { referrer: currentLocation }
  }}
/>

// 采用push生成新的记录
<Redirect push to="/somewhere/else" />

// 配合Switch组件使用,form表示重定向之前的路径,如果匹配则重定向,不匹配则不重定向
<Switch>
  <Redirect from='/old-path' to='/new-path'/>
  <Route path='/new-path' component={Place}/>
</Switch>
复制代码

Switch

路由切换,只会匹配第一个路由,可以想象成tab栏
Switch内部只能包含Route、Redirect、Router

<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/:user" component={User}/>
  <Route component={NoMatch}/>
</Switch>
复制代码

withRouter

当一个非路由组件也想访问到当前路由的match,location,history对象,那么withRouter将是一个非常好的选择,可以理解为将一个组件包裹成路由组件

import { withRouter } from 'react-router-dom'
const MyComponent = (props) => {
    const { match, location, history } = this.props
     return (
        <div>{props.location.pathname}</div>
    )
}
const FirstTest = withRouter(MyComponent);
复制代码

history对象

用过vue的都知道,vue-router有组件形式的导航,也有编程式导航,那react-router怎么使用api来控制前进后退和刷新呢?这就需要我们来说明下history对象的作用了

其实在每个路由组件中我们可以使用this.props.history获取到history对象,也可以使用withRouter包裹组件获取,
在history中封装了push,replace,go等方法,具体内容如下

History {
    length: number;
    action: Action;
    location: Location;
    push(path: Path, state?: LocationState): void; // 调用push前进到一个地址,可以接受一个state对象,就是自定义的路由数据
    push(location: LocationDescriptorObject): void; // 接受一个location的描述对象
    replace(path: Path, state?: LocationState): void; // 用页面替换当前的路径,不可再goBack
    replace(location: LocationDescriptorObject): void; // 同上
    go(n: number): void; // 往前走多少也页面
    goBack(): void; // 返回一个页面
    goForward(): void; // 前进一个页面
    block(prompt?: boolean | string | TransitionPromptHook): UnregisterCallback;
    listen(listener: LocationListener): UnregisterCallback;
    createHref(location: LocationDescriptorObject): Href;
}
复制代码

这样我们想使用api来操作前进后退就可以调用history中的方法啦

参考文档