2018-12-21路由
1.路由
React路由依赖于React Router,React Router保持UI和与URL的同步。它拥有简单的API与强大的功能,如:代码缓冲加载,动态路由匹配,建立正确的位置过渡处理。
示例:
import React, { Component } from 'react'
import { render } from 'react-dom'
import { Router, Route, IndexRoute, Link, browserHistory } from 'react-router'
const ACTIVE = { color: 'red' }
class App extends Component {
render() { return (<div><h1>我的路由</h1>
<ul>
<li><Link to="/" activeStyle={ACTIVE}>首页</Link></li>
<li><Link to="/users" activeStyle={ACTIVE}>用户页</Link></li>
</ul>
{this.props.children}
</div>)}}
class Index extends React.Component {
render() {return (<div><h2>Index!</h2></div>)}}
class Users extends React.Component {
render() {return (<div><h2>Users</h2></div>)}}
render((
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Index}/>
<Route path="users" component={Users}></Route>
</Route>
</Router>
), document.getElementById('app'))
注意:react-router的版本v4.0与之前的版本变化较大,所以现在以最新v4.0的为准。并且react-router有react-router-dom和react-router-native之分,一个是web版本,一个是移动App版本。
React-router有三大组件,一个是Router,一个是Link,另外一个是Route。
1)Router相当于一个容器,不会被渲染出来,其他组件必须放到router中才能使用到react-router的功能。根据功能的不同,还分为BrowserRouter和MemoryRouter等
BrowserRouter主要使用在浏览器中,它利用HTML5 的history API来同步URL和UI的变化。当我们点击了程序中的一个链接之后,BrowserRouter就会找出与这个URL匹配的Route,并将他们渲染出来。 既然BrowserRouter是用来管理我们的组件的,那么它当然要被放在最顶级的位置,而我们的应用程序的组件就作为它的一个子组件而存在。
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(<BrowserRouter><app/></BrowserRouter>,document.body);
有时候我们的应用只是整个系统中的一个模块,比如一个使用了ASPNET MVC中的area的后台管理模块,应用中的URL总是以 http://localhost/admin/ 开头。这种情况下我们总不能每次定义Link和Route的时候都带上admin吧?react-router已经考虑到了这种情况,所以为我们提供了一个basename属性。为BrowserRouter设置了basename之后,Link中就可以省略掉admin了,而最后渲染出来的URL又会自动带上admin。
<BrowserRouter basename="/admin"/>
<Link to="/home"/> // 被渲染为 <a href="/admin/home">
</BrowserRouter>
2)Link被渲染成为一个a标签,通常以声明的方式被定义。
Link就像是一个个的路牌,为我们指明组件的位置。Link使用声明式的方式为应用程序提供导航功能,定义的Link最终会被渲染成一个a标签。Link使用to这个属性来指明目标组件的路径,可以直接使用一个字符串,也可以传入一个对象。
// 字符串参数查询
<Link to="/query">查询</Link>
// 对象参数
<Link to={{
pathname: '/query',
search: '?key=name',
hash: '#hash'
}}>查询</Link>
Link提供的功能并不多,好在我们还有NavLink可以选择。NavLink是一个特殊版本的Link,可以使用activeClassName来设置Link被选中时被附加的class,使用activeStyle来配置被选中时应用的样式。此外,还有一个exact属性,此属性要求location完全匹配才会附加class和style。这里说的匹配是指地址栏中的URl和这个Link的to指定的location相匹配。
// 选中后被添加class selectedHome
<NavLink to={'/'} exact activeClassName='selected'>Home</NavLink>
// 选中后被附加样式 color:red
<NavLink to={'/gallery'} activeStyle={{color:red}}>Gallery</NavLink>
3)Route包含一个path,并指明了path与URL匹配时渲染的组件。
Route应该是react-route中最重要的组件了,它的作用是当location与Route的path匹配时渲染Route中的Component。如果有多个Route匹配,那么这些Route的Component都会被渲染。
与Link类似,Route也有一个exact属性,作用也是要求location与Route的path绝对匹配。
// 当location形如 http://location/时,Home就会被渲染。
// 因为 "/" 会匹配所有的URL,所以这里设置一个exact来强制绝对匹配。
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
Route的三种渲染方式:
a) component
b) render - render的类型是function,Route会渲染这个function的返回值。因此它的作用就是附加一些额外的逻辑。
<Route path="/home" render={() => { return (<div>Home</div>);}/>
c) children - 这是最特殊的渲染方式。一、它同render类似,是一个function。不同的地方在于它会被传入一个match参数来告诉你这个Route的path和location匹配上没有。二、第二个特殊的地方在于,即使path没有匹配上,我们也可以将它渲染出来。秘诀就在于前面一点提到的match参数。我们可以根据这个参数来决定在匹配的时候渲染什么,不匹配的时候又渲染什么。
// 在匹配时,容器的calss是light,<Home />会被渲染
// 在不匹配时,容器的calss是dark,<About />会被渲染
<Route path='/home' children={({ match }) => (<div className={{match?'light':'dark'}>
{match?<Home/>:<About/>} </div>)}/>
所有路由中指定的组件将被传入以下三个props: match, location, history.
match.params.透过这个属性,我们可以拿到从location中解析出来的参数。对应的,我们的Route的path也要使用特殊的写法。
如下示例,三个Link是一个文章列表中三个链接,分别指向三篇id不同的文章。而Route用于渲染文章详情页。注意path='/p/:id' ,location中的对应的段会被解析为id=1 这样的键值。最终这个键值会作为param的键值存在。Route中的组件可以使用this.props.match.params.id来获取,示例中使用了结构赋值。
<Link to='/p/1' />
<Link to='/p/2' />
<Link to='/p/3' />
<Route path='/p/:id' render={(match)=<h3>当前文章ID:{match.params.id}</h3>)} />
Redirect
当这个组件被渲染是,location会被重写为Redirect的to指定的新location。它的一个用途是登录重定向,比如在用户点了登录并验证通过之后,将页面跳转到个人主页
<Redirect to="/new"/>