本文从属于笔者的 React入门与最佳实践 系列 ,是对于 React Router最新指南与异步加载实践 的补充
在正常的Route项配置中 <Route path="messages/:id" component={Message} />
,在component这个Prop中我们传入的是某个组件名,而如果我们需要在路由配置时动态构造一些组件,譬如我们希望传入标题为 HelloWorld
的 Message
组件时,我们会需要以下配置:
const TitledMessage = ()=>{<Message title="HelloWorld" /> }
这里是传入了一个函数式声明的组件,关于函数式声明的组件可以参考 React中函数式声明组件。 。而React Router官方也提供了我们另一种动态构造组件的方式,即是所谓的NamedComponent,即允许在子路由声明时将Props值作为路由配置参数传入父路由,譬如我们创建了需要传入两个Props参数的组件:
const NamedComponents = (props) => ( <div> {props.title}<br /> {props.subTitle} </div> )
而NamedComponent需要的两个输入参数其实也是两个可组合的组件:
const Title = () => ( <h1>Hello from Title Component</h1> ) const SubTitle = () => ( <h1>Hello from SubTitle Component</h1> )
然后我们可以为NamedComponent组件创建一个单独的路由,而其默认子路由可以是两个组件:
<Route path='/namedComponent' component={NamedComponents}> <IndexRoute components={{ title: Title, subTitle: SubTitle }} /> </Route>
最后的效果如下所示:
很多应用的不可或缺的一个点就是从URL中读取路由参数,React Router自然也为我们提供了路由参数设置与读取的功能,譬如在定义路由时,我们可以直接将参数定义入路由中:
<Route path='/about/:name' component={About} />
而在需要读取该参数的组件中:
const About = (props) => ( <div> <h3>Welcome to the About Page</h3> <h2>{props.params.name}</h2> </div> )
有时候,我们也需要设置可选参数,譬如如果按照上面的配置方案我们直接访问 /#/about
是无法访问到About组件的,有点类似于正则表达式的写法:
<Route path='/about(/:name)' component={About} />
另有一个小Trick,有时候我们在组件内部展示元素的时候是需要根据是否有参数传入然后再判断是否需要显示:
{ props.params.name && <h2>Hello, {props.params.name}</h2>}
上文介绍的是按照路由参数的方式进行参数传递,就像HTTP URL标准一样,有时候我们也需要按照查询参数的方式来进行参数传递,譬如我们定义了如下基于查询参数的组件:
const Query = (props) => ( <h2>{props.location.query.message}</h2> )
然后我们需要在刚才构建好的路由地址中添加上该组件:
... <Route path='/address' component={Address}> <IndexRoute component={TwitterFeed} /> <Route path='instagram' component={Instagram} /> <Route path='query' component={Query} /> </Route> ...
而对应的带参数传递的跳转到该组件的Link为:
<IndexLink activeClassName='active' to={{ pathname: '/address/query', query: { message: 'Hello from Route Query' } }}>Route Query</IndexLink>
最后,我们在官方的总的例子中来看下两种参数的使用:
import React from 'react' import { render } from 'react-dom' import { browserHistory, Router, Route, Link } from 'react-router' import withExampleBasename from '../withExampleBasename' const User = ({ params: { userID }, location: { query } }) => { let age = query && query.showAge ? '33' : '' return ( <div className="User"> <h1>User id: {userID}</h1> {age} </div> ) } const App = ({ children }) => ( <div> <ul> <li><Link to="/user/bob" activeClassName="active">Bob</Link></li> <li><Link to={{ pathname: '/user/bob', query: { showAge: true } }} activeClassName="active">Bob With Query Params</Link></li> <li><Link to="/user/sally" activeClassName="active">Sally</Link></li> </ul> {children} </div> ) render(( <Router history={withExampleBasename(browserHistory, __dirname)}> <Route path="/" component={App}> <Route path="user/:userID" component={User} /> </Route> </Router> ), document.getElementById('example'))