在使用React-transition-group做路由动画的时候,经常因为code spliting导致动画无效。原因 多半是由于路由钩子动画执行的时候组件并未加载到。所以观察DOM结构中并未发现react动画相关的 钩子class。这就需要我们在做代码拆分的时候做写细节处理。
// route.js
import React, { Suspense } from "react";
import ReactDOM from 'react-dom';
import { HashRouter as Router, Route, Switch } from "react-router-dom";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import './app.css';
// 代码code spliting
const Index = React.lazy(() => import("./pages/index"));
const About = React.lazy(() => import("./pages/about"));
const Home = React.lazy(() => import("./pages/home"));
// 注意:这里的div为外层动画的挂载点。
// page内部的节点异步挂载
const wrap = WrappedComponent => () => (
<div className="page">
<Suspense fallback={null}>
<WrappedComponent />
</Suspense>
</div>
);
function App() {
return (
<Router>
<Route
render={({ location }) => (
<TransitionGroup>
<CSSTransition
key={location.pathname}
classNames="page"
appear
timeout={850}
>
<Switch location={location}>
<Route exact path="/" component={wrap(Index)} />
<Route exact path="/home" component={wrap(Home)} />
<Route exact path="/about" component={wrap(About)} />
</Switch>
</CSSTransition>
</TransitionGroup>
)}
/>
</Router>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
下面是三个被拆分的示例组件代码
// index.js
import React, { Component } from "react";
import { Link } from "react-router-dom";
export default class Index extends Component {
render() {
return (
<div
className="index"
style={{
backgroundColor: "rgb(255,80,61)"
}}
>
<h1>Index Page</h1>
<p>
<Link to="/">index</Link>
<Link to="/home">home</Link>
<Link to="/about">about</Link>
</p>
</div>
);
}
}
// home.js
import React, { Component } from "react";
import { Link } from "react-router-dom";
export default class Index extends Component {
render() {
return (
<div
className="home"
style={{
backgroundColor: "rgb(78,133,255)"
}}
>
<h1>Home Page</h1>
<p>
<Link to="/">index</Link>
<Link to="/home">home</Link>
<Link to="/about">about</Link>
</p>
</div>
);
}
}
// about.js
import React, { Component } from "react";
import { Link } from "react-router-dom";
export default class Index extends Component {
render() {
return (
<div
className="about"
style={{
backgroundColor: "rgb(0,163,58)"
}}
>
<h1>About Page</h1>
<p>
<Link to="/">index</Link>
<Link to="/home">home</Link>
<Link to="/about">about</Link>
</p>
</div>
);
}
}
样式文件
/*app.css */
.page {
position: absolute;
top: 0;
left: 0;
right: 0;
}
.page-appear {
opacity: 0;
top: 20px;
}
.page-appear-active {
opacity: 1;
top: 0;
transition: opacity 550ms ease-in, top 550ms ease-in;
}
.page-enter {
opacity: 0;
top: 20px;
}
.page-enter-active {
opacity: 1;
top: 0;
transition: opacity 550ms ease-in 300ms, top 550ms ease-in 300ms;
}
.page-exit {
opacity: 1;
top: 0;
}
.page-exit-active {
opacity: 0;
top: 20px;
transition: opacity 250ms ease, top 250ms ease;
}