04.React Router
React Router
中心化路由
基本的
<Router history={appHistory}>
<Route path="/" component={withRouter(App)}>
<IndexRoute component={withRouter(ClusterTabPane)} />
<Route path="cluster" component={withRouter(ClusterTabPane)} />
</Route>
<Route path="*" component={withRouter(ErrorPage)} />
</Router>
不过
{this.props.children}
中。在一个多页面的应用程序中,如果我们不使用
import React from "react";
import { render } from "react-dom";
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);
可以看出,在原始的多页面程序配置下,我们需要在render
函数中手动地根据传入的
在
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
);
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);
在router
对象通过this.context
进行传递,不过这种方式往往会引起莫名的错误。因此在withRouter
函数来方便进行封装:
import React from "react";
import { withRouter } from "react-router";
const Page = React.createClass({
componentDidMount() {
this.props.router.setRouteLeaveHook(this.props.route, () => {
if (this.state.unsaved)
return "You have unsaved information, are you sure you want to leave this page?";
});
},
render() {
return <div>Stuff</div>;
}
});
export default withRouter(Page);
然后在某个具体的组件内部,可以使用this.props.router
来获取router
对象
router.push("/users/12");
// or with a location descriptor object
router.push({
pathname: "/users/12",
query: { modal: true },
state: { fromDashboard: true }
});
- replace(pathOrLoc):Identical to push except replaces the current history entry with a new one.
- go(n):Go forward or backward in the history by n or -n.
- goBack():Go back one entry in the history.
- goForward():Go forward one entry in the history.
const Home = withRouter(
React.createClass({
componentDidMount() {
this.props.router.setRouteLeaveHook(
this.props.route,
this.routerWillLeave
);
},
routerWillLeave(nextLocation) {
// return false to prevent a transition w/o prompting the user,
// or return a string to allow the user to decide:
if (!this.state.isSaved)
return "Your work is not saved! Are you sure you want to leave?";
} // ...
})
);
除了跳转确认之外,Route也提供了钩子函数以通知我们当路由发生时的情况,可以有助于我们进行譬如页面权限认证等等操作onLeave
onEnter
如果我们在history
对象进行手动跳转
// your main file that renders a Router
import { Router, browserHistory } from 'react-router'
import routes from './app/routes'
render(<Router history={browserHistory} routes={routes}/>, el)
// somewhere like a redux/flux action file:
import { browserHistory } from 'react-router'
browserHistory.push('/some/path')