React-Router (1)

2017-12-06  本文已影响0人  祁稷

首先对于 react 来说,即便是没有使用 react-route 也是可以完成需求的,使用 react 提供的 this.state.route 可以渲染不同的页面,虽然使用起来简单,但是面对稍微复杂点儿的应用就会变得有心无力(例如嵌套,列表等结构)。

这个时候,需要使用 React-route 重构应用。

import React from 'react'
import { render } from 'react-dom'
//(1):引入 react-route
import { Router Route Link } from 'react-route'
const App = React.createClass({
    render (){
        return (
            <div>
                <ul>
                    {/* 需要把之前的 a 标签替换为 Link 标签 */}
                    <li><Link to='/about'>About</li>
                    <li><Link to='/inbox'>Inbox</li>
                </ul>
                {/* 之前用的是一个 Child 的小组件,现在替换为{this.props.children} */}
            </div>
        )
    }
})

重要的部分来了,我们用一些 <Route> 来渲染 <Router>
创建一个 <Route>,这里面是一个一般的嵌套路由

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

实际上,route 通过内部处理,将一个完整的路径 /about 自动搭建成 <App><About /></App> ,将你写的树级嵌套结构转变成真正的路由配置,同时也可以用对象(如果不用 JSX 的语法)的方式替代:

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

渲染组件的时候,react-route 会自动注入一些东西,偶其实动态部分的东西,比如::id

路径中的信息可以通过 this.props.params.id 去获取它,也可以通过访问 this.props.location.query.bar 来获取 /foo?bar=baz 这样URL的 "baz"

(2)React-Route 基础路由配置

路由配置的本质是 一组告诉 route 如何匹配 URL,并且如何执行的的指令。

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)

这段代码是一个标准的不得了的 react-route 代码(官方示例代码,可不TM标准吗)。

URL 组件
/ App
/about App / about
/inbox App / inbox
/inbox/messages:id App / inbox / messages

(1)嵌套路由

URL 组件
/ App
/about App / about
/inbox App / inbox
/inbox/messages:id App / inbox / messages

(2)解决父路由的默认页面问题
这个时候有一个问题,当 URl 为 / 的时候,我们无法找到这个页面,因为即使加载了App的这个组件,由于是嵌套路由的非最底层,那么 this.props.children 是 undefined,IndexRoute 这个东西可以帮我们默认一个页面,所以上面那个表格有了新的变化。
在标准代码中 path="/" 的路由标签里面加上 <IndexRoute component={Dashboard} />

URL 组件
/ App / Dashboard
/about App / about
/inbox App / inbox
/inbox/messages:id App / inbox / messages
URL 组件
/ App / Dashboard
/about App / about
/inbox App / inbox
/messages:id App / inbox/ messages

(3)解决URl解耦
这个是一个非常容易遇到的问题,我们的 route 如果嵌套的足够多,会使URL变得异常复杂,那么一个简洁的 URL 是必不可少的,我们可以用 绝对路径
将标准代码里面的 <Route path="messages/:id" component={Message} /> path 内容改成 /messages/:id ,虽然是多了一个 "/",但是我们的 URL 就变成了这个样子

URL 组件
/ App / Dashboard
/about App / about
/inbox App / inbox
/messages:id App / inbox/ messages

(4)我们改变了这个 URL ,但访问原来的 URL 会弹出错误页面
我们可以用 <Redirect from = "messages:id" to = "/messages:id">
将之加一个重定向的路由,就不论怎么访问,只要符合要求的就直接跳转过来

(5)题外话,Hook
Hook 是在路由跳转的过程中,两个状态。

整体的改变后的代码是如下:

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)

需要引入

import { Redirect } from 'react-router'

在嵌套路由中,还有一个优先级的概念:
由于路由算法是从上至下,所以兄弟节点路由配置时,前一个路由节点不能匹配到后一个路由节点。

上一篇下一篇

猜你喜欢

热点阅读