首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >react-router学习笔记

react-router学习笔记

作者头像
Tiffany_c4df
发布于 2020-09-24 09:32:30
发布于 2020-09-24 09:32:30
2.9K00
代码可运行
举报
文章被收录于专栏:前端小课堂前端小课堂
运行总次数:0
代码可运行

react-router学习笔记 author: @TiffanysBear

基本介绍

React Router 是完整的 React 路由解决方案

React Router 保持 UI 与 URL 同步。它拥有简单的 API 与强大的功能例如代码缓冲加载、动态路由匹配、以及建立正确的位置过渡处理。

基础部分

路由配置

index路由配置:添加首页,设置默认页面,使用 IndexRoute

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { IndexRoute } from 'react-router'

const Dashboard = React.createClass({
  render() {
    return <div>Welcome to the app!</div>
  }
})

React.render((
  <Router>
    <Route path="/" component={App}>
      {/* 当 url 为/时渲染 Dashboard */}
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

重定向 Redireact

通过 <Redirect> 中的 from 和 to 进行路由的重定向。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Redirect } from 'react-router'

React.render((
	<Router>
		<Route>
			<Redirect from="messages/:id" to="/messages/:id" />
		</Route>
	</Router>
));

进入和离开的 Hook

Route 可以定义 onEnter 和 onLeave 两个 hook ,这些hook会在页面跳转确认时触发一次。这些 hook 对于一些情况非常的有用,例如权限验证或者在路由跳转前将一些数据持久化保存起来。

在路由跳转过程中,onLeave hook 会在所有将离开的路由中触发,从最下层的子路由开始直到最外层父路由结束。然后onEnter hook会从最外层的父路由开始直到最下层子路由结束。

继续我们上面的例子,如果一个用户点击链接,从 /messages/5 跳转到 /about,下面是这些 hook 的执行顺序:

  • /messages/:id 的 onLeave
  • /inbox 的 onLeave
  • /about 的 onEnter

路由配置方式

可以使用标签形式,也可以使用路由配置的方式进行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const routeConfig = [
  { path: '/',
    component: App,
    indexRoute: { component: Dashboard },
    childRoutes: [
      { path: 'about', component: About },
      { path: 'inbox',
        component: Inbox,
        childRoutes: [
          { path: '/messages/:id', component: Message },
          { path: 'messages/:id',
            onEnter: function (nextState, replaceState) {
              replaceState(null, '/messages/' + nextState.params.id)
            }
          }
        ]
      }
    ]
  }
]

React.render(<Router routes={routeConfig} />, document.body)

路由匹配原理

如何看是否匹配一个 URL 呢?

  • 嵌套关系:深度优先遍历整个路由配置
  • 路径语法:相对路径的话,会根据嵌套关系,与自身路径进行拼接;绝对路径会忽略嵌套关系
  • 优先级:路由算法会根据定义的顺序自顶向下匹配路由,要注意前一个路由不会被后一个路由匹配所忽略替换。

History

React Router 是建立在 history 上的,简而言之,一个 history 知道如何去监听浏览器地址栏的变化, 并解析这个 URL 转化为 location 对象, 然后 router 使用它匹配到路由,最后正确地渲染对应的组件。

常见的 history 有三种形式:

  • browserHistory
  • hashHistory
  • createMemoryHistory

三者之间的区别:

browserHistory

Browser history 是使用 React Router 的应用推荐的 history。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/some/path这样真实的 URL 。 真实路由需要服务器也进行相应的配置。

hashHistory

Hash history 使用 URL 中的 hash(#)部分去创建形如 example.com/#/some/path 的路由。 Hash history 不需要服务器任何配置就能运行,但是不推荐在实际线上环境中使用。

像这样 ?_k=ckuvup 没用的在 URL 中是什么?(用来作为恢复 location state 的唯一 key 标识) 当一个 history 通过应用程序的 push 或 replace 跳转时,它可以在新的 location 中存储 “location state” 而不显示在 URL 中,这就像是在一个 HTML 中 post 的表单数据。

在 DOM API 中,这些 hash history 通过 window.location.hash = newHash 很简单地被用于跳转,且不用存储它们的location state。但我们想全部的 history 都能够使用location state,因此我们要为每一个 location 创建一个唯一的 key,并把它们的状态存储在 session storage 中。当访客点击“后退”和“前进”时,我们就会有一个机制去恢复这些 location state。

createMemoryHistory

Memory history 不会在地址栏被操作或读取。这就解释了我们是如何实现服务器渲染的。同时它也非常适合测试和其他的渲染环境(像 React Native )。

和另外两种history的一点不同是你必须创建它,这种方式便于测试。

默认路由 IndexRoute

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

IndexLink

如果你在这个 app 中使用 Home , 它会一直处于激活状态,因为所有的 URL 的开头都是 / 。 这确实是个问题,因为我们仅仅希望在 Home 被渲染后,激活并链接到它。

如果需要在 Home 路由被渲染后才激活的指向 / 的链接,请使用 Home

高级用法

动态路由

代码分拆,按需加载。 React Router 里的路径匹配以及组件加载都是异步完成的,不仅允许你延迟加载组件,并且可以延迟加载路由配置。在首次加载包中你只需要有一个路径定义,路由会自动解析剩下的路径。 配合webpack,根据路由拆分组件,按需加载。

跳转前确认

React Router 提供一个 routerWillLeave 生命周期钩子,这使得 React 组件可以拦截正在发生的跳转,或在离开 route 前提示用户。routerWillLeave 返回值有以下两种:

return false 取消此次跳转 return 返回提示信息,在离开 route 前提示用户进行确认。 你可以在 route 组件 中引入 Lifecycle mixin 来安装这个钩子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Lifecycle } from 'react-router'

const Home = React.createClass({

  // 假设 Home 是一个 route 组件,它可能会使用
  // Lifecycle mixin 去获得一个 routerWillLeave 方法。
  mixins: [ Lifecycle ],

  routerWillLeave(nextLocation) {
    if (!this.state.isSaved)
      return 'Your work is not saved! Are you sure you want to leave?'
  },

  // ...

})

服务端渲染

服务端渲染与客户端渲染有些许不同,因为你需要:

发生错误时发送一个 500 的响应 需要重定向时发送一个 30x 的响应 在渲染之前获得数据 (用 router 帮你完成这点) 为了迎合这一需求,你要在 API 下一层使用:

使用 match 在渲染之前根据 location 匹配 route 使用 RoutingContext 同步渲染 route 组件 它看起来像一个虚拟的 JavaScript 服务器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { renderToString } from 'react-dom/server'
import { match, RoutingContext } from 'react-router'
import routes from './routes'

serve((req, res) => {
  // 注意!这里的 req.url 应该是从初始请求中获得的
  // 完整的 URL 路径,包括查询字符串。
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.send(500, error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
      res.send(200, renderToString(<RoutingContext {...renderProps} />))
    } else {
      res.send(404, 'Not found')
    }
  })
})

至于加载数据,你可以用 renderProps 去构建任何你想要的形式——例如在 route 组件中添加一个静态的 load 方法,或如在 route 中添加数据加载的方法——由你决定。 这块需要仔细了解一下具体的实现和原理。

组件生命周期

在路由切换期间,组件生命周期的变化。 https://react-guide.github.io/react-router-cn/docs/guides/advanced/ComponentLifecycle.html

所有的之前已经被挂载的组件,组件内部 props 参数的更新,走的是 componentWillReceiveProps ,所以只是从 router 更新了 props。

在组件外部使用导航

组件内部导航使用 this.context.router,外部的使用 history 实现组件外部的导航。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// your main file that renders a Router
import { Router, browserHistory } from 'react-router'
import routes from './app/routes'
render(<Router history={browserHistory} routes={routes}/>, el)

// somewhere like a redux/flux action file:
import { browserHistory } from 'react-router'
browserHistory.push('/some/path')

使用技巧

代码分割

通过 react-loadable,可以做到路由级别动态加载,或者更细粒度的模块级别动态加载:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const AsyncHome = Loadable({
    loader: () => import('../components/Home/Home'),
    loading: LoadingPage
})

<Route exact path="/" component={AsyncHome} />

当然上面展示的是 ReactRouter 中的用法,AsyncHome 可以在任何 JSX 中引用,这样就提升到了模块级别的动态加载。

注意,无论是 webpack 的 Tree Shaking,还是动态加载,都只能以 Commonjs 的源码为分析目标,对 node_modules 中代码不起作用,所以 npm 包请先做好拆包。或者类似 antd 按照约定书写组件,并提供一种 webpack-loader 自动完成按需加载。

转场动画 - 路由切换时转场动画

通过 React Router Transition (Ant Motion 也很好用) 可以实现路由级别的动画:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Router>
  <AnimatedSwitch
    atEnter={{ opacity: 0 }}
    atLeave={{ opacity: 0 }}
    atActive={{ opacity: 1 }}
    className="switch-wrapper"
  >
    <Route exact path="/" component={Home} />
    <Route path="/about/" component={About}/>
    <Route path="/etc/" component={Etc}/>
  </AnimatedSwitch>
</Router>

并提供了一些生命周期的回调,具体可以参考文档。现在动画的思路比较靠谱的也大致是这种:通过添加/移除 class 的方式,利用 css3 做动效。

滚动条复位

当页面回退时,将滚动条恢复到页面最顶部,可以让单页路由看起来更加正常。由于 React Router4.0 中,路由是一种组件,我们可以利用 componentDidUpdate 简单完成滚动条复位的功能:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Router history={history}>
  <ScrollToTop>
    <div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="*" component={NotFound} />
      </Switch>
    </div>
  </ScrollToTop>
</Router>
@withRouter
class ScrollToTop extends Component {
    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            window.scrollTo(0, 0)
        }
    }

    render() {
        return this.props.children
    }
}

非通过 Route 渲染的组件,可以通过 withRouter 拿到路由信息,仅当其为 Router 的子元素时有效。

嵌套路由

React Router4.0 嵌套路由与 3.0 不同,是通过组件 Route 的嵌套实现的。

在任何组件,都可以使用如下代码实现嵌套路由:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Route path={`${this.props.match.url}/:id`} component={NestComponent} />

这样将路由功能切分到各个组件中,我现在的项目甚至已经没有 route.js 文件了,路由由 layout 与各个组件自身承担。这种设计思路与 Nestjs 的描述性路由具有相同的思想 - 在 nodejs 中,我们可以通过装饰器,在任意一个 Action 上描述其访问的 URL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@POST("/api/service")
async someAction() {}

常见的使用和属性

  • : 渲染第一个被匹配到的路由
  • withRouter : 为组件注入

服务端渲染原理 React SSR

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
react-router之onEnter和onLeave
在之前介绍过react-router的使用,在这里我们介绍一下路由的onEnter和onLeave,顾名思义,分别是路由进入之前和路由离开之前,我们可以在这段时间内做一些处理。比如下面这个例子
OECOM
2020/07/01
2.2K0
react-router实现机制
react-router使用方式 react-router是专为React设计的路由解决方案,以react component的方式提供API,包含常用的Router,Route,IndexRedir
IMWeb前端团队
2017/12/29
1.5K0
React Router基础教程
然后就可以直接使用 ReactRouter 这个对象了,我们可能会使用到其中的几个属性
书童小二
2018/09/03
1K0
React Router基础教程
React Router 邦邦两拳🥊 🥊
这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」 简介
用户4793865
2023/01/12
3.8K0
React Router 使用教程
真正学会 React 是一个漫长的过程。 你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系。想要发挥它的威力,整个技术栈都要配合它改造。你要学习一整套解决方案,从后端到前端,都是全新的做法。
ruanyf
2018/04/12
2.4K0
React Router 使用教程
react-router 中 IndexRoute、IndexRedirect 的区别介绍
本文内容引用了 react-router v3 的文档介绍来举例说明,内容并不重复,我们会以项目开发的角度来分析这两个功能的实际作用,更有助于理解和使用这两个功能。
我与梦想有个约会
2020/01/04
2.4K0
说说React-Router底层实现?-面试进阶
对于React-Router是针对React定义的路由库,用于将URL和component进行匹配。
beifeng1996
2022/10/10
4560
手写React-Router源码,深入理解其原理
上一篇文章我们讲了React-Router的基本用法,并实现了常见的前端路由鉴权。本文会继续深入React-Router讲讲他的源码,套路还是一样的,我们先用官方的API实现一个简单的例子,然后自己手写这些API来替换官方的并且保持功能不变。
蒋鹏飞
2020/10/15
1.7K0
手写React-Router源码,深入理解其原理
React Router 之 browserHistoryHistoriesHistories
前端工程采用 SPA 模式 hashHistory , 在集成到生产环境中的时候,使用browserHistory :
一个会写诗的程序员
2018/08/17
9620
react-router 入门笔记
React-router 笔记 官方文档 基本思路 react-router 通过react 组件的方式实现, 路由相关的数据,通过props传递给组件调用, 路由层级关系, 通过标签嵌套实现 基础标签 BrowserRouter : 路由容器 该组件只能包含单个元素 Route : 组件渲染出口 必须包含在 BrowserRouter 中 exact 精确匹配 Link : 跳转链接 必须包含在 BrowserRouter 中 基本使用 // react-router-demo import
copy_left
2019/08/21
1.7K0
React-Router
​ react-router是核心部分。react-router-dom提供了浏览器使用需要的定制组件。react-router-native则专门提供了在原生移动应用中需要用到的部分。
Cloud-Cloudys
2020/07/06
2.6K0
React Router V6详解
SAP全称是【single-page application】,中文译为单页面应用。它是网站应用的一种模型,可以动态重写当前的页面来与用户交互,而不需要重新加载整个页面。相对于传统的 Web 应用程序,单页应用做到了前后端分离,即后端只负责处理数据提供接口,而页面逻辑和页面渲染都交由前端处理。前端发展到现在,单页应用的使用已经很广泛,目前时兴的 React、Vue、Angular 等前端框架均采用了 SPA 原则。
xiangzhihong
2023/01/06
8.3K0
web前端经典react面试题
React-Router 支持使用 hash(对应 HashRouter)和 browser(对应 BrowserRouter) 两种路由规则, react-router-dom 提供了 BrowserRouter 和 HashRouter 两个组件来实现应用的 UI 和 URL 同步:
beifeng1996
2022/12/19
1.1K0
React Router3到5 升级小记
不光是你在用,我们很多项目也在用,懒得升级,感觉改动太大,升级了后谁知道会出什么问题,别没事找事。
zz_jesse
2020/03/17
2.4K0
React 进阶 - React Router
用 React 或者 Vue 构建的应用都是单页面应用,单页面应用是使用一个 HTML 前提下,一次性加载 JavaScript , CSS 等资源,所有页面都在一个容器页面下,页面切换实质是组件的切换。
Cellinlab
2023/05/17
2.2K0
React 进阶 - React Router
React-Router V6 使用详解
2.去除Switch中的<Redirect>,用react-router-dom中的Redirect 替代,或者用 <Navigate> 实现
程序狗
2021/12/17
4K0
React Router5 感性认知
本文主要是了解下 react-router 新版本一些理念,为我们以后的开发注入一些感性认知。
zz_jesse
2020/03/17
1.6K0
react+redux+webpack教程4
接着上回新闻搜索的例子。现在我们要通过路由进入一个新的页面来查看新闻详细内容。 react和路由并没有什么直接关系,用什么路由都可以。不过使用react-router可以让我们的代码风格统一, 并且有些工具使用起来很方便。 先来安装react-router库(我目前安装的版本是2.0.1,跟1.x版本区别比较大): npm install react-router --save 从使用上来说,react-router不过是一些react组件,所以用起来特别方便。不用多说,看个例子就知道怎么用了。 先把咱们已
前朝楚水
2018/04/03
1.9K0
滴滴前端二面常考react面试题(持续更新中)_2023-03-01
refs允许你直接访问DOM元素或组件实例。为了使用它们,可以向组件添加个ref属性。
用户10376779
2023/03/01
4.8K0
react-router 环境使用锚点的方法
锚点是通过在界面中增加一些特征(比如 id),然后在 URL 地址后面加上 #id 就可以访问到指定页面的指定位置,这样可以让我们快速跳转到页面的某个位置,但是在 react-router 中这种方法遇到了问题,因为 react-router 会把 # 当做是 hash 来处理。导致即使跳转到指定页面后,# 后面的锚点也不生效。针对这个问题,在 react-router 的一个 issue 中大家也展开了激烈的讨论。以下是我看过以后整理的几种解决办法。 只有某些页面需要 当只有某些页面需要使用锚点的时候,可
我与梦想有个约会
2018/07/02
3.1K0
相关推荐
react-router之onEnter和onLeave
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档