1. 使用react-router
用嵌套的<Router/>来定义视图的层级,当Route激活时提供React的元素来处理这些Route
React Router会根据URL来匹配最深层级的Route, 然后激活嵌套在UI里面的该Route的整个分支
你只需简单使用<RouteHandle/>组件来渲染激活的子Router
var App = React.createClass({ render: function () { return ( <div> <header> <ul> <li><Link to="app">Dashboard</Link></li> <li><Link to="inbox">Inbox</Link></li> <li><Link to="calendar">Calendar</Link></li> </ul> Logged in as Jane </header> {/* this is the important part */} <RouteHandler/> </div> ); } });
var routes = ( <Route name="app" path="/" handler={App}> <Route name="inbox" handler={Inbox}/> <Route name="calendar" handler={Calendar}/> <DefaultRoute handler={Dashboard}/> </Route> ); Router.run(routes, function (Handler) { React.render(<Handler/>, document.body); });(都不带任何参数)
当我们登录/inbox时,名字为inbox的route会匹配上,而且他的父route app也会匹配. run方法会回调接收者Handler, 因此所有匹配上的信息都会被执行.
渲染Handler确实仅仅渲染App,因为它是最高的匹配上的route handler. 因为 inbox 是激活的child route, 在 App 中渲染<RouteHandler/>时会渲染 Inbox 元素, <RouteHandler /> 和 Ember中的{{outlet}}或Angular中的<div ng-view/>相同.
注意到我们不需要 <Header/> 元素,因为我们没必要重复它. React Router会为我们共享UI
2. 更多嵌套
嵌套深层UI也不是问题,比如 Inbox 页面, 它的左边是个消息管理列表, 右边是消息详细内容,上面是工具条. 工具条和消息列表是固定的,消息内容随着对列表的点击变化.
React Router handle是这样的:
var Inbox = React.createClass({ render: function () { return ( <div> <Toolbar/> <Messages/> <RouteHandler/> </div> ); } }); var routes = ( <Route handler={App}> <Route name="inbox" handler={Inbox}> <Route name="message" path=":messageId" handler={Message}/> <DefaultRoute handler={InboxStats}/> </Route> <Route name="calendar" handler={Calendar}/> <DefaultRoute handler={Dashboard}/> </Route> );Inbox 现在在它的渲染方法里有了一个<RouterHandler/>, 就像它的父元素
我们现在增加了子route在inbox里, 消息和状态的页面可以在里面渲染
3. 动态部分
我们增加消息接口时,引入了'动态部分'到URL里.这部分从url中解析,并在 run 的回调里获取, 或者从 this.context.router router处理器中. 下面展示一下如何访问到参数
Remember our message route looks like this:
<Route name="message" path=":messageId" handler={Message}/>
Lets look at accessing the messageId
in Message
.
var Message = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
render: function () {
return (
<div>{this.context.router.getCurrentParams().messageId}</div>
);
}
});
Assuming the user navigates to /inbox/123
, this.context.router.getCurrentParams().messageId
is going to be '123'
.
Alternatively, you can pass the param data down through the view hierarchy from the run
callback and access the params with this.props.params
.
Router.run(routes, function (Handler, state) {
var params = state.params;
React.render(<Handler params={params}/>, document.body);
});
(state.params是获取的url参数??)
// and then pass the params down to every use of `<RouteHandler/>`
<RouteHandler {...this.props}/>
// Inbox ends up looking like this
var Inbox = React.createClass({
render: function () {
return (
<div>
<Toolbar/>
<Messages/>
<RouteHandler {...this.props}/> // 这里传递下去
</div>
);
}
});
// and Message changes to:
var Message = React.createClass({
render: function () {
return (
<div>{this.props.params.messageId}</div> // 这里使用
);
}
});
4. 关于动态部分的重点
detail切换的时候,以下方法不会被执行:getInitialState
,componentWillMount
, componentWillUnmount
or componentDidMount
如果想要强制re-mount,可以赋一个唯一的key值