从2.8.x升到4.x,路途艰辛,网上资料不多,许多东西只能硬啃了,把官网例子的重点翻译一遍,让自己好理解也提高下翻译水平。
之前的程序路由之前跳转频繁,一方面客户体验不好,另一方面回退时的状态保持问题非常让人头疼,故此升级到react-router4.3.1使用modal模式能解决这个问题。
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
// This example shows how to render two different screens
// (or the same screen in a different context) at the same url,
// depending on how you got there.
// 该例子演示了如何在同一个URL页面渲染两个不同的页面或在不同上下文中的同一页面
//
// Click the colors and see them full screen, then "visit the
// gallery" and click on the colors. Note the URL and the component
// are the same as before but now we see them inside a modal
// on top of the old screen.
// 点击颜色可以在全屏状态下查看他们,然后点击“visit the gallery"后再次点击色块。
// 注意此时的URL和组件,虽然他们和之前一样但现在他们却以模态窗口的形式显示在旧页面之上。
class ModalSwitch extends React.Component {
// We can pass a location to <Switch/> that will tell it to
// ignore the router's current location and use the location
// prop instead.
// 我们可以传递location给<Switch/>组件,这可以让它优先展示我们传递的location而忽略路由当前的location。
// We can also use "location state" to tell the app the user
// wants to go to `/img/2` in a modal, rather than as the
// main page, keeping the gallery visible behind it.
// 我们也可以使用”location state"通知app,我们想使用modal的方式将`/img/2`显示在gallery之上。
// Normally, `/img/2` wouldn't match the gallery at `/`.
// So, to get both screens to render, we can save the old
// location and pass it to Switch, so it will think the location
// is still `/` even though its `/img/2`.
// 通常,`/img/2`并不匹配`/`路由,所以,为了同时显示两个路由,我们将之前的location保存并传递给Switch,
// 让组件认为当前仍然是`/`,尽管此时已经是`/img/2`了
// 保存之前的location
previousLocation = this.props.location;
componentWillUpdate(nextProps) {
const { location } = this.props;
// set previousLocation if props.location is not modal
// 如果之前的location不是modal显示,设置previousLocation属性,后期将传递给Switch
if (nextProps.history.action !== "POP" && (!location.state || !location.state.modal)) {
this.previousLocation = this.props.location;
}
}
render() {
const { location } = this.props;
// 判断当前路由是否为modal模式
const isModal = !!(
location.state &&
location.state.modal &&
this.previousLocation !== location
); // not initial render
return (
<div>
<Switch location={isModal ? this.previousLocation : location}>
<Route exact path="/" component={Home} />
<Route path="/gallery" component={Gallery} />
<Route path="/img/:id" component={ImageView} />
</Switch>
{isModal ? <Route path="/img/:id" component={Modal} /> : null}
</div>
);
}
}
const IMAGES = [
{ id: 0, title: "Dark Orchid", color: "DarkOrchid" },
{ id: 1, title: "Lime Green", color: "LimeGreen" },
{ id: 2, title: "Tomato", color: "Tomato" },
{ id: 3, title: "Seven Ate Nine", color: "#789" },
{ id: 4, title: "Crimson", color: "Crimson" }
];
const Thumbnail = ({ color }) => (
<div
style={{
width: 50,
height: 50,
background: color
}}
/>
);
const Image = ({ color }) => (
<div
style={{
width: "100%",
height: 400,
background: color
}}
/>
);
const Home = () => (
<div>
<Link to="/gallery">Visit the Gallery</Link>
<h2>Featured Images</h2>
<ul>
<li>
<Link to="/img/2">Tomato</Link>
</li>
<li>
<Link to="/img/4">Crimson</Link>
</li>
</ul>
</div>
);
const Gallery = () => (
<div>
{IMAGES.map(i => (
<Link
key={i.id}
to={{
pathname: `/img/${i.id}`,
// this is the trick!
state: { modal: true }
}}
>
<Thumbnail color={i.color} />
<p>{i.title}</p>
</Link>
))}
</div>
);
const ImageView = ({ match }) => {
const image = IMAGES[parseInt(match.params.id, 10)];
if (!image) {
return <div>Image not found</div>;
}
return (
<div>
<h1>{image.title}</h1>
<Image color={image.color} />
</div>
);
};
const Modal = ({ match, history }) => {
const image = IMAGES[parseInt(match.params.id, 10)];
if (!image) {
return null;
}
const back = e => {
e.stopPropagation();
history.goBack();
};
return (
<div
onClick={back}
style={{
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
background: "rgba(0, 0, 0, 0.15)"
}}
>
<div
className="modal"
style={{
position: "absolute",
background: "#fff",
top: 25,
left: "10%",
right: "10%",
padding: 15,
border: "2px solid #444"
}}
>
<h1>{image.title}</h1>
<Image color={image.color} />
<button type="button" onClick={back}>
Close
</button>
</div>
</div>
);
};
const ModalGallery = () => (
<Router>
<Route component={ModalSwitch} />
</Router>
);
export default ModalGallery;
重点理解Switch组件location属性。