美文网首页
React学习 —— react-router

React学习 —— react-router

作者: yozosann | 来源:发表于2019-05-27 16:18 被阅读0次

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

React Router 保持 UI 与 URL 同步。它拥有简单的 API 与强大的功能例如代码缓冲加载、动态路由匹配、以及建立正确的位置过渡处理。你第一个念头想到的应该是 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)

通过上面的配置,这个应用知道如何渲染下面四个 URL:

URL 组件

  • /:App
  • /about:App -> About
  • /inbox:App -> Inbox
  • /inbox/messages/:id:App -> Inbox -> Message

添加首页

想象一下当 URL 为 / 时,我们想渲染一个在 App 中的组件。不过在此时,Apprender 中的 this.props.children 还是 undefined。这种情况我们可以使用 IndexRoute 来设置一个默认页面。

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)

URL 组件

  • /:App -> Dashboard
  • /about:App -> About
  • /inbox:App -> Inbox
  • /inbox/messages/:id:App -> Inbox -> Message

让 UI 从 URL 中解耦出来

并且还能够让 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 组件

  • /:App -> Dashboard
  • /about:App -> About
  • /inbox:App -> Inbox
  • /messages/:id:App -> Inbox -> Message

兼容旧的 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)

顾名思义,现在当有人点击 /inbox/messages/5 这个链接,他们会被自动跳转到 /messages/5

进入和离开的Hook

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

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

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

  • /messages/:idonLeave
  • /inboxonLeave
  • /aboutonEnter

替换的配置方式

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)

路由匹配原理

  • 嵌套关系:React Router深度优先遍历整个路由配置来找到一个与给定URL匹配的路由。
  • 路径语法:路由路径是匹配一个(或一部分)URL 的 一个字符串模式
    • :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

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

  • 优先级:按照书写顺序优先匹配:
<Route path="/comments" ... />
<Redirect from="/comments" ... />

Redirect将不会被匹配到。

Histories

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

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

// JavaScript 模块导入(译者注:ES6 形式)
import { browserHistory } from 'react-router'

render(
  <Router history={browserHistory} routes={routes} />,
  document.getElementById('app')
)

browserHistory

Browser history 是使用 React Router 的应用推荐的 history。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/some/path这样真实的 URL 。
这个需要服务端处理,将所有路由全部达到前端的静态资源上。

app.get('*', function (request, response){
  response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})

hashHistory

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

Hash history 不需要服务器任何配置就可以运行,如果你刚刚入门,那就使用它吧。但是我们不推荐在实际线上环境中用到它,因为每一个 web 应用都应该渴望使用 browserHistory。

默认路由(IndexRoute)与 IndexLink

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

例如我们的url是, www.xxx.com。这个时候匹配到了/,但是并匹配不到accounts和statements,那么页面的内容就是空的,为了解决这样的情况我们就引入了:

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

这个时候访问到/的时候就会存在一个默认的组件。

Index Links

如果你在这个 app 中使用<Link to="/">Home</Link>, 它会一直处于激活状态,因为所有的 URL 的开头都是 / 。 这确实是个问题,因为我们仅仅希望在 Home 被渲染后,激活并链接到它。
如果需要在 Home 路由被渲染后才激活的指向 / 的链接,请使用<IndexLink to="/">Home</IndexLink>

相关文章

网友评论

      本文标题:React学习 —— react-router

      本文链接:https://www.haomeiwen.com/subject/durhtctx.html