[技术分享]ES6 中的 React-Router 介绍
lczimu123发布于2 年前 • 474 次阅读
简介: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表示的是默认子路由。