【React Router】React Router学习笔记

这篇具有很好参考价值的文章主要介绍了【React Router】React Router学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

React Router

【React Router】React Router学习笔记,React,学习,笔记,react.js

1.什么是React Router?

React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步。

2.为什么要用React Router?

  1. React Router 知道如何为我们搭建嵌套的 UI,因此我们不用手动找出需要渲染哪些 <Child> 组件。
  2. 获取URL参数。当渲染组件时,React Router 会自动向 Route 组件中注入一些有用的信息,尤其是路径中动态部分的参数。

3.基础

3.1 路由配置

路由配置是一组指令,用来告诉 router 如何匹配 URL以及匹配后如何执行代码。

示例:

import React from 'react'
import { Router, Route, Link } from 'react-router'

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})

const About = React.createClass({
  render() {
    return <h3>About</h3>
  }
})

const Inbox = React.createClass({
  render() {
    return (
      <div>
        <h2>Inbox</h2>
        {this.props.children || "Welcome to your Inbox"}
      </div>
    )
  }
})

const Message = React.createClass({
  render() {
    return <h3>Message {this.props.params.id}</h3>
  }
})

React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

可以使用IndexRoute给路径/添加默认首页

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)

现在,Apprender 中的 this.props.children 将会是 <Dashboard>这个元素。

现在的sitemap如下所示:

URL 组件
/ App -> Dashboard
/about App -> About
/inbox App -> Inbox
/inbox/messages/:id App -> Inbox -> Message

绝对路径可以将 /inbox/inbox/messages/:id 中去除,并且还能够让 Message 嵌套在 App -> Inbox 中渲染。

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* 使用 /messages/:id 替换 messages/:id */}
        <Route path="/messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

在多层嵌套路由中使用绝对路径使我们无需在 URL 中添加更多的层级,从而可以使用更简洁的 URL。

绝对路径可能在动态路由中无法使用。

上面的修改使得URL发生了改变,我们可以使用Redirect来兼容旧的URL。

import { Redirect } from 'react-router'

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Dashboard} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="/messages/:id" component={Message} />

        {/* 跳转 /inbox/messages/:id 到 /messages/:id */}
        <Redirect from="messages/:id" to="/messages/:id" />
      </Route>
    </Route>
  </Router>
), document.body)

3.2 路由匹配原理

路由拥有三个属性来决定是否“匹配“一个 URL:

  1. 嵌套关系

    嵌套路由被描述成一种树形结构。React Router 会深度优先遍历整个路由配置来寻找一个与给定的 URL 相匹配的路由。

  2. 路径语法

    :paramName – 匹配一段位于 /?# 之后的 URL。 命中的部分将被作为一个参数
    () – 在它内部的内容被认为是可选的

    *– 匹配任意字符(非贪婪的)直到命中下一个字符或者整个 URL 的末尾,并创建一个 splat 参数

    <Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
    <Route path="/hello(/:name)">       // 匹配 /hello, /hello/michael 和 /hello/ryan
    <Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg
    

    如果一个路由使用了相对路径,那么完整的路径将由它的所有祖先节点的路径和自身指定的相对路径拼接而成。使用绝对路径可以使路由匹配行为忽略嵌套关系。

  3. 优先级

    路由算法会根据定义的顺序自顶向下匹配路由。因此,当拥有两个兄弟路由节点配置时,必须确认前一个路由不会匹配后一个路由中的路径。例如:

    <Route path="/comments" ... />
    <Redirect from="/comments" ... />
    

3.3 History

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

常用的 history 有三种形式, 但也可以使用 React Router 实现自定义的 history

  • browserHistory
  • hashHistory
  • createMemoryHistory
3.3.1 browerHistory

Browser history 是使用 React Router 的应用推荐的 history。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/some/path这样真实的 URL 。

3.3.2 hashHistory

Hash history 使用 URL 中的 hash(#)部分去创建形如 example.com/#/some/path 的路由。

3.3.3 createMemoryHistory

Memory history 不会在地址栏被操作或读取。同时它也非常适合测试和其他的渲染环境(像 React Native )。这种history需要创建。

const history = createMemoryHistory(location)
3.3.4 实现示例
import React from 'react'
import { render } from 'react-dom'
import { browserHistory, Router, Route, IndexRoute } from 'react-router'

import App from '../components/App'
import Home from '../components/Home'
import About from '../components/About'
import Features from '../components/Features'

render(
	<Router history={browserHistory}>
        <Route path='/' component={App}>
            <IndexRoute component={Home} />
            <Route path='about' component={About} />
            <Route path='features' component={Features} />
        </Route>
    </Router>,
    document.getElementById('app')
)

3.4 默认路由(IndexRoute)与IndexLink

3.4.1 IndexRoute

当用户访问 / 时, App 组件被渲染,但组件内的子元素却没有, App 内部的 this.props.children 为 undefined 。Home 无法参与到比如 onEnter hook 这些路由机制中来。 在 Home 的位置,渲染的是 AccountsStatements。 router 允许使用 IndexRoute ,以使 Home 作为最高层级的路由出现。

<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

现在 App 能够渲染 {this.props.children} 了, 也有了一个最高层级的路由,使 Home 可以参与进来。

3.4.2 IndexLink

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

4.高级用法

4.1 动态路由

React Router 里的路径匹配以及组件加载都是异步完成的,不仅允许延迟加载组件,并且可以延迟加载路由配置。

React Router 会逐渐的匹配 URL 并只加载该 URL 对应页面所需的路径配置和组件。

结合Webpack可以在路由发生改变时,资源按需加载。

const CourseRoute = {
  path: 'course/:courseId',

  getChildRoutes(location, callback) {
    require.ensure([], function (require) {
      callback(null, [
        require('./routes/Announcements'),
        require('./routes/Assignments'),
        require('./routes/Grades'),
      ])
    })
  },

  getIndexRoute(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./components/Index'))
    })
  },

  getComponents(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./components/Course'))
    })
  }
}

4.2 跳转前确认

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

  1. return false 取消此次跳转
  2. return 返回提示信息,在离开 route 前提示用户进行确认。

可以在 route 组件 中引入 Lifecycle mixin 来安装这个钩子。

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?'
  },

  // ...

})

推荐使用 React.createClass 来创建组件,初始化路由的生命周期钩子函数。

如果想在一个深层嵌套的组件中使用 routerWillLeave 钩子,只需在 route 组件 中引入 RouteContext mixin,这样就会把 route 放到 context 中。

import { Lifecycle, RouteContext } from 'react-router'

const Home = React.createClass({

  // route 会被放到 Home 和它子组件及孙子组件的 context 中,
  // 这样在层级树中 Home 及其所有子组件都可以拿到 route。
  mixins: [ RouteContext ],

  render() {
    return <NestedForm />
  }

})

const NestedForm = React.createClass({

  // 后代组件使用 Lifecycle mixin 获得
  // 一个 routerWillLeave 的方法。
  mixins: [ Lifecycle ],

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

  // ...

})

4.3 服务端渲染

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

  • 发生错误时发送一个 500 的响应

  • 需要重定向时发送一个 30x 的响应

  • 在渲染之前获得数据 (用 router 完成这点)

为了迎合这一需求,要在 API 下一层使用:

  • 使用 match 在渲染之前根据location 匹配 route
  • 使用 RoutingContext 同步渲染 route 组件
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')
    }
  })
})

4.4 组件生命周期

假如路由配置如下:

<Route path="/" component={App}>
  <IndexRoute component={Home}/>
  <Route path="invoices/:invoiceId" component={Invoice}/>
  <Route path="accounts/:accountId" component={Account}/>
</Route>

路由切换时,组件生命周期的变化情况如下:

  1. 当用户打开应用的/页面

    组件 生命周期
    App componentDidMount
    Home componentDidMount
    Invoice N/A
    Account N/A
  2. 当用户从/跳转到/invoice/123

    组件 生命周期
    App componentWillReceiveProps,componentDidUpdate
    Home componentWillUnmount
    Invoice componentDidMount
    Account N/A
    • App 从 router 中接收到新的 props(例如 childrenparamslocation 等数据), 所以 App 触发了 componentWillReceivePropscomponentDidUpdate 两个生命周期方法
    • Home 不再被渲染,所以它将被移除
    • Invoice 首次被挂载
  3. 当用户从/invoice/123跳转到/invoice/789

    组件 生命周期
    App componentWillReceiveProps,componentDidUpdate
    Home N/A
    Invoice componentWillReceiveProps,componentDidUpdate
    Account N/A

    所有的组件之前都已经被挂载, 所以只是从 router 更新了 props.

  4. 当从/invoice/789跳转到/accounts/123

    组件 生命周期
    App componentWillReceiveProps,componentDidUpdate
    Home N/A
    Invoice componentWillUnmount
    Account componentDidMount

虽然还有其他通过 router 获取数据的方法, 但是最简单的方法是通过组件生命周期 Hook 来实现。示例如下,在 Invoice 组件里实现一个简单的数据获取功能。

let Invoice = React.createClass({

  getInitialState () {
    return {
      invoice: null
    }
  },

  componentDidMount () {
    // 上面的步骤2,在此初始化数据
    this.fetchInvoice()
  },

  componentDidUpdate (prevProps) {
    // 上面步骤3,通过参数更新数据
    let oldId = prevProps.params.invoiceId
    let newId = this.props.params.invoiceId
    if (newId !== oldId)
      this.fetchInvoice()
  },

  componentWillUnmount () {
    // 上面步骤四,在组件移除前忽略正在进行中的请求
    this.ignoreLastFetch = true
  },

  fetchInvoice () {
    let url = `/api/invoices/${this.props.params.invoiceId}`
    this.request = fetch(url, (err, data) => {
      if (!this.ignoreLastFetch)
        this.setState({ invoice: data.invoice })
    })
  },

  render () {
    return <InvoiceView invoice={this.state.invoice} />
  }
})

4.5 组件外部跳转

虽然在组件内部可以使用 this.context.router 来实现导航,但许多应用想要在组件外部使用导航。使用Router组件上被赋予的history可以在组件外部实现导航。文章来源地址https://www.toymoban.com/news/detail-720857.html

// 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 Router】React Router学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【React】react-router 路由详解

    🚩🚩🚩 💎个人主页: 阿选不出来 💨💨💨 💎个人简介: 一名大二在校生,学习方向前端,不定时更新自己学习道路上的一些笔记. 💨💨💨 💎目前开发的专栏: JS 🍭Vue🍭React🍭 💨💨💨 前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,根据不同的url地

    2024年02月01日
    浏览(40)
  • React-路由 react-router-dom

    前端路由的功能:让用户从一个页面跳转到另一个页面。 前端路由是一套映射规则 ,在 React 中, 是 URL 路径与组件的对应关系 。 使用 React 路由简单来说就是配置 路径与组件(配对) 。 路由的本质: 一个路径 path 对应唯一的一个组件 component 当我们访问一个 path 自动把 p

    2024年02月02日
    浏览(43)
  • React 路由react-router-dom详解

    前面我们先了解一下 路由是什么? 路由分类有哪些?内置API有哪些 ? 可能有点枯燥,不喜欢看的直接跳过 ! 单页Web应用(single page web application,SPA)。 整个应用只有一个完整的页面。 点击页面中的链接不会刷新页面,只会做页面的局部更新。 数据都需要通过ajax请求获取

    2023年04月11日
    浏览(42)
  • react学习笔记——1. hello react

    包含的包一共有4个,分别的作用如下: babel.min.js:可以进行ES6到ES5的语法转换;可以用于import;可以用于将jsx转换为js。注意,在开发的时候,这个转换(jsx转换js)不在线上使用,因为转换需要时间,页面可能会出现白屏。 react.development.js:react的核心代码库,引入以后,

    2024年02月14日
    浏览(34)
  • 创建react脚手架项目——demo(react18 + react-router 6)+ react项目打包部署

    全局安装 create-react-app 说明:不建议安装全局,建议使用 npx 命令安装,具体可参考官网,如下: 官网: https://zh-hans.legacy.reactjs.org/docs/create-a-new-react-app.html. 1.2.1 问题1——npm ERR! code ENOTFOUND(网络问题clashx) 问题描述,如下: 解决问题——方式1 如果使用了clashx,可能是它

    2024年02月07日
    浏览(73)
  • 怎么理解React Router

    React Router就是实现不用刷新的条件下切换不同页面。路由的本质是页面URL发生改变,页面的显示结果也发生改变,但是页面不会刷新。 React Router分为几个部分: React-Router:实现了路由核心部分功能; React-Router-dom:基于react-router,加入了在浏览器运行环境下的一些功能; r

    2024年04月27日
    浏览(30)
  • React Router的使用

    React Router 是 React 项目的路由库,使用很方便,也是 React 前端项目的主要功能库之一。这里的路由指的是客户端的路由,在客户端路由时,浏览器是不会发送页面请求的,只会发送数据请求。 安装依赖 主要组件 首先创建一个 Router,这里创建的是 BrowserRouter,还有其他类型的

    2024年04月27日
    浏览(33)
  • React学习笔记01-React的基本认识

    React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决 定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源 了。 轻量级的视图层库!A JavaScript library for building user interfaces React不是一个完整的

    2024年02月08日
    浏览(36)
  • React07-路由管理器react-router-dom(v6)

    react-router 是一个流行的用于 React 应用程序路由的库。它使我们能够轻松定义应用程序的路由,并将它们映射到特定的组件,这样可以很容易地创建复杂的单页面应用,并管理应用程序的不同视图。 react-router 是基于 React 构建的,因此与其他 React 库和工具集成得很好。它在许

    2024年02月02日
    浏览(42)
  • React Router 6 快速上手

    React Router 以三个不同的包发布到 npm 上,它们分别为: react-router: 路由的核心库,提供了很多的:组件、钩子。 react-router-dom: 包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如 BrowserRouter 等 。 react-router-native: 包括react-router所有内容,并添加一些专门用于ReactNa

    2024年02月11日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包