React Router 4 简易入门
原文 React Router4是一个流行的纯React重写的包。现在的版本中已不需要路由配置,现在一切皆组件。 本文涵盖了开始使用React Router构建网站所需要的一切知识。我们将会为本地运动队制作一个网站。 代码想看网站最终效果,查看demo 安装React Router被拆分成三个包: 进行网站(将会运行在浏览器环境中)构建,我们应当安装 npm install --save react-router-dom 路由器(Router)在你开始项目前,你需要决定你使用的路由器的类型。对于网页项目,存在 通常,我们更倾向选择<BrowserRouter>,但如果你的网站仅用来呈现静态文件,那么<HashRouter>将会是一个好选择。 对于我们的项目,将设将会有服务器的动态支持,因此我们选择<BrowserRouter>作为路由器组件。 历史(History)每个路由器都会创建一个history对象并用其保持追踪当前 渲染<Router>路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个 import { BrowserRouter } from 'react-router-dom' ReactDOM.render(( <BrowserRouter> <App /> </BrowserRouter> ),document.getElementById('root')) <App>应用通过 // this component will be rendered by our <___Router> const App = () => ( <div> <Header /> <Main /> </div> ) 注意:你可以按你喜欢的方式对应用布局,但是将路由与导航拆分出来对于这个入门教程会成家简单。 路由(Route)<Route>组件是React Router中主要的结构单元。在任意位置只要匹配了URL的路径名(pathname)你就可以创建<Route>元素进行渲染。 路径(Path)<Route>接受一个数为string类型的 <Route path='/roster'/> // 当路径名为'/'时,path不匹配 // 当路径名为'/roster'或'/roster/2'时,path匹配 // 当你只想匹配'/roster'时,你需要使用"exact"参数 // 则路由仅匹配'/roster'而不会匹配'/roster/2' <Route exact path='/roster'/> 注意:在匹配路由时,React Router只关注location的路径名。当URL如下时: http://www.example.com/my-projects/one?extra=false React Router去匹配的只是'/my-projects/one'这一部分。 匹配路径
使用route tester这款工具来对路由与URL进行检验。 注意:本例中路由路径仅支持绝对路径[注4]。 创建你的路由可以在路由器(router)组件中的任意位置创建多个<Route>,但通常我们会把它们放在同一个位置。使用<Switch>组件来包裹一组<Route>。<Switch>会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染。 对于本网站,我们希望匹配一下路径:
为了在应用中能匹配路径,在创建<Route>元素时必须带有需要匹配的path作为参数。 <Switch> <Route exact path='/' component={Home}/> {/* both /roster and /roster/:number begin with /roster */} <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch> <Route>是如何渲染的?当一个路由的path匹配成功后,路由用来确定渲染结果的参数有三种。只需要提供其中一个即可。
<Route path='/page' component={Page} /> const extraProps = { color: 'red' } <Route path='/page' render={(props) => ( <Page {...props} data={extraProps}/> )}/> <Route path='/page' children={(props) => ( props.match ? <Page {...props}/> : <EmptyPage {...props}/> )}/> 通常 通过<Route>渲染的元素会被传入一些参数。分别是match对象,当前location对象[注6]以及history对象(由router创建)[注7]。 <Main>现在我们清楚了根路由的结构,我们需要实际渲染我们的路由。对于这个应用,我们将会在<Main>组件中渲染<Switch>与<Route>,这一过程会将route匹配生成的HTML放在<main>节点中。 import { Switch,Route } from 'react-router-dom' const Main = () => ( <main> <Switch> <Route exact path='/' component={Home}/> <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch> </main> ) 注意:主页路由包含额外参数。该参数用来保证路由能准确匹配path。 嵌套路由运动员路由 在<Roster>组件中,我们将为两种路径进行渲染:
例如,<Roster>用来渲染所有以 const Roster = () => ( <div> <h2>This is a roster page!</h2> <Switch> <Route exact path='/roster' component={FullRoster}/> <Route path='/roster/:number' component={Player}/> </Switch> </div> ) 路径参数有时路径名中存在我们需要获取的参数。例如,在运动员界面,我们需要获取运动员的编号。我们可以向route的路径字符串中添加path参数 如'/roster/:number'中 { number: '6' } // 注获取的值是字符串类型的 <Player>组件可以使用props.match.params对象来确定需要被渲染的运动员的数据。 // 返回运动员对象的API import PlayerAPI from './PlayerAPI' const Player = (props) => { const player = PlayerAPI.get( parseInt(props.match.params.number,10) ) if (!player) { return <div>Sorry,but the player was not found</div> } return ( <div> <h1>{player.name} (#{player.number})</h1> <h2>{player.position}</h2> </div> ) 你可以通过阅读path-to-regexp文档来了解更多。 除了<Player>组件,我们的页面还包含<FullRoster>,<Schedule>以及 <Home>组件。 const FullRoster = () => ( <div> <ul> { PlayerAPI.all().map(p => ( <li key={p.number}> <Link to={`/roster/${p.number}`}>{p.name}</Link> </li> )) } </ul> </div> ) const Schedule = () => ( <div> <ul> <li>6/5 @ Evergreens</li> <li>6/8 vs Kickers</li> <li>6/14 @ United</li> </ul> </div> ) const Home = () => ( <div> <h1>Welcome to the Tornadoes Website!</h1> </div> ) Link现在,我们应用需要在各个页面间切换。如果使用锚点元素(就是)实现,在每次点击时页面将被重新加载。React Router提供了<Link>组件用来避免这种状况的发生。当你点击<Link>时,URL会更新,组件会被重新渲染,但是页面不会重新加载。 import { Link } from 'react-router-dom' const Header = () => ( <header> <nav> <ul> <li><Link to='/'>Home</Link></li> <li><Link to='/roster'>Roster</Link></li> <li><Link to='/schedule'>Schedule</Link></li> </ul> </nav> </header> ) <Link>使用'to'参数来描述需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。如果其值为字符床将会被转换为location对象。 <Link to={{ pathname: '/roster/7' }}>Player #7</Link> 注意:本例的link的pathname属性只能是绝对路径[注4]。 例子一个完整的网站例子 获取路由希望当下你已准备好深入构建你自己的网站了。 我们已经了解了构建网站所需要的所有必须组件(<BrowserRouter>,<Route>,以及 <Link>)。当然,还有一些我们没有涉及的组件。所幸React Router拥有优质的文档,你可以查看并从中了解更多的信息。文档也提供一系列的例子与源代码。 注释:[1] locations 是一个含有描述URL不同部分属性的对象: // 一个基本的location对象 { pathname: '/',search: '',hash: '',key: 'abc123' state: {} } [2] 你可以渲染无路径的<Route>,其将会匹配所有location。此法用于访问存在上下文中的变量与方法。 [3] 如果你使用children参数,即便在当前location不匹配时route也将进行渲染。 [4] 当需要支持相对路径的<Route>与<Link>时,你需要多做一些工作。相对<Link>将会比你之前看到的更为复杂。因其使用了父级的match对象而非当前URL来匹配相对路径。 [5] 这是一个本质上无状态的函数组件。内部实现,component参数与render参数的组件是用很大的区别的。使用component参数的组件会使用 <Route path='/one' component={One}/> // React.createElement(props.component) <Route path='/two' render={() => <Two />}/> // props.render() [6]?<Route>与<Switch>组件都会带有location参数。这能让你使用与实际location不同的location去匹配地址。 [7]?可以传入staticContext参数,不过这仅在服务端渲染时有用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |