[技术分享]ES6 中的 React-Router 介绍

lczimu123发布于4 个月前 • 165 次阅读

简介:React由一套完整的路由机制,下面我们根据官方文档,来了解一下官方路由React-router

1.路由的本质:是通过hash值不同,显示不同的页面,因为不用刷新整个页面,就能切换显示,因此通过这

种路由机制,我们可以实现单页应用。

首先:我们来自己写一个袖珍型的路由。

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)

这里有一些ES6的语法,比如说ES6中函数的调用以及es6中const定义常量。

从实现结果我们发现,当hash值不同的时候,可以实现不同的跳转,并且页面是没有刷新的。

2.通过React-router实现路由的原理

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

// First we import some modules...
import { Router, Route, IndexRoute, Link, hashHistory } from 'react-router'

// Then we delete a bunch of code from App and
// add some <Link> elements...
const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        {/* change the <a>s to <Link>s */}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>

        {/*
          next we replace `<Child>` with `this.props.children`
          the router will figure out the children for us
        */}
        {this.props.children}
      </div>
    )
  }
})

// Finally, we render a <Router> with some <Route>s.
// It does all the fancy routing stuff for us.
render((
  <Router history={hashHistory}>
    <Route path="/" component={App}>
      <IndexRoute component={Home} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox} />
    </Route>
  </Router>
), document.body)

我们这里通过{this.props.children}的方法来代替了,这里我们通过这段代码简单的实现了路由,我

发现App默认是子路由的父组件,所以我们可以通过this.props.children来显示子组件。

访问效果:与1.我们自定义的路由完全相同。

那么相对于1.我们自己写的路由,React-router有什么好处呢?我们不需要去一个个指明组路由或者说父组

组件所需要包含的子组件。

如果不习惯,通过JSX语法来写路由,React-router也有一种js的方式来配置路由:

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

这里官方给的例子是有问题的,官方给了下面的例子:

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

但是history是2.x版本中用到,应该改成:

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

注意:官方推荐的是使用browserHistory,因为browserHistory利用了H5的history API,但是因为访问的是实际真实的地址,如果使用browserHistory,则需要在服务器端做相应的配置,否则刷新后页面404。而通过hashHistory,使用的是hash地址,没有访问真实的URL,因此不需要特意在服务器端做配置。

2.下一步,我们讲的是更进一步的UI路由,在UI插件中传值,也就是在路由的同时传参。

// Make a new component to render inside of Inbox
const Message = React.createClass({
  render() {
    return <h3>Message</h3>
  }
})

const Inbox = React.createClass({
  render() {
    return (
      <div>
        <h2>Inbox</h2>
        {/* Render the child route component */}
        {this.props.children}
      </div>
    )
  }
})

render((
  <Router history={history}>
    <Route path="/" component={App}>
      <IndexRoute component={Home} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* add some nested routes where we want the UI to nest */}
        {/* render the stats page when at `/inbox` */}
        <IndexRoute component={InboxStats}/>
        {/* render the message component at /inbox/messages/123 */}
        <Route path="messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

这里,当我们访问/inbox/message:1234,实际上页面显示的组件结构为:

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

也就是,我们再路由的同时,给子组件传递了参数id,可以通过在子组件中this.props.params.id来得到。

当然如果我们正常访问/inbox得到的还是:

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

这里的IndexRoute表示的是默认子路由。

共收到 0 条回复