React Router基本用法

本文同步自我的博客 Reeoo's Blog,欢迎移步前往,^_^

概览

本文基于React Router v1.03版本。

React Router是一个为React设计的强大的路由库。可以帮助我们快速的实现路由功能,包括URLReact components之间的同步映射关系。
在解释React Router如何使用之前,我们先来看看在不使用React Router的情况下,是怎么样的,接下来的所有例子中都将使用ES2015语法和语言特性。

不使用React Router

import React from 'react'
import { render } from 'react-dom'

const About = React.createClass({/*...*/})
const Inbox = React.createClass({/*...*/})
const Home = React.createClass({/*...*/})

const App = React.createClass({
getInitialState() {
  return {
    route: window.location.hash.substr(1)
  }
},componentDidMount() {
  window.addEventListener('hashchange',() => {
    this.setState({
      route: window.location.hash.substr(1)
    })
  })
},render() {
  let Child
  switch (this.state.route) {
    case '/about': Child = About; break;
    case '/inbox': Child = Inbox; break;
    default:      Child = Home;
  }

  return (
    <div>
      <h1>App</h1>
      <ul>
        <li><a href="#/about">About</a></li>
        <li><a href="#/inbox">Inbox</a></li>
      </ul>
      <Child/>
    </div>
  )
}
})

render(<App />,document.body)

hash值变化的时候,App 将会根据this.state.route 的值决定渲染哪个组件(AboutIndexHome)到页面上。这样的做法虽然看起来很简单,但是也增加了复杂性。

想象一下,如果组件 Inbox 有一些嵌套的子组件,它们的路由规则可能是这样的:/inbox/message/12345 或者 /inbox/unread 这样的,
上面的路由匹配规则很显然就不能满足我们的需求了,我们不得不修改之前的URL解析规则,写一堆复杂的代码来判断哪种URL应该呈现哪个组件(比如:App -> About,App -> Inbox -> Messages -> Message,App -> Inbox -> Messages -> Stats)。

使用React Router

首先,引入React Router

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

把判断路由逻辑的那段代码删除,然后加入Link标签

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        {/* 把`a`标签换成`Link`标签 */}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>

        {/*
          把`<Child>`替换成`this.props.children`
          路由会渲染正确的组件
        */}
        {this.props.children}
      </div>
    )
  }
})

最后引入<Router><Route>,由它们帮我们搞定路由。

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

React Router知道哪种URL规则下,渲染哪个组件到页面上,不需要我们自己在做任何的判断。
例如:/about这种URL规则,会被构建成<App><About /></App>
React Router内部,会把<Route>标签层级转换成路由配置。如果你不喜欢jsx的这种写法,也可以使用对象的形式:

const routes = {
  path: '/',component: App,childRoutes: [
    { path: 'about',component: About },{ path: 'inbox',component: Inbox },]
}

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

添加更多的视图

OK,现在在inbox路由下嵌套一个messages子路由,
首先需要添加一个新的Message组件:

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

然后在原有的inbox路由下面为 Message 组件添加新的路由,这样就可以得到嵌套的组件。

const Inbox = React.createClass({
  render() {
    return (
      <div>
        <h2>Inbox</h2>
        {/* 渲染子组件 */}
        {this.props.children}
      </div>
    )
  }
})

render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* 在这里加入要嵌套的视图 */}
        {/* render the stats page when at `/inbox` */}
        <IndexRoute component={InboxStats}/>
        {/* 渲染message组件  /inbox/messages/123 */}
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
),document.body)

访问inbox/messages/12345会匹配新加的路由,App->Inbox->Message,路由层级:

<App>
  <Inbox>
    <Message params={ {id: '12345'} } />
  </Inbox>
</App>

访问/inbox,路由层级:

<App>
    <Inbox>
      <InboxStats />
    </Inbox>
</App>

获取参数

当我们访问inbox/messages/12345的时候,我们需要获取到相应的参数,然后从服务器获取对应的数据。当视图渲染的时候,路由组件会注入一些有用的属性到组件上,特别是一些从URL动态获取的参数信息,在我们这个示例里是:id

const Message = React.createClass({

  componentDidMount() {
    // from the path `/inbox/messages/:id`
    const id = this.props.params.id

    fetchMessage(id,function (err,message) {
      this.setState({ message: message })
    })
  },// ...

})

你也可以通过查询串来获取参数,假如我们在浏览器里面访问/foo?bar=baz这个路由,在你的组件中可以通过this.props.location.query.bar获取bar的值baz

总结

React Router基本用法大概就这么多,一个应用往往是各种组件各种嵌套,搞明白了React Router,就可以很轻松的玩转路由。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom