资讯专栏INFORMATION COLUMN

【译】只需四个步骤:使用 React 实现页面过渡动画

moven_j / 1679人阅读

摘要:翻译疯狂的技术宅作者英文标题英文地址说明本文首发于公众号在本文中,我将向你展示如何使用和库中的生命周期方法来实现页面的过渡效果。我们还用创建了一个变量,可以用它来对封装的子组件中的的不同样式属性实现动画效果。用渲染,并且或者插入动画状态值。

</>复制代码

  1. 翻译:疯狂的技术宅
    作者:Martin Haagensli
    英文标题:Animated page transitions with React Router 4, ReactTransitionGroup and Animated
    英文地址:https://hackernoon.com/animat...
    说明:本文首发于公众号:jingchengyideng

在本文中,我将向你展示如何使用 ReactTransitionGroup 和 Animated 库中的生命周期方法来实现页面的过渡效果。

你可以通过这个视频 http://animate.mhaagens.me 来观看演示效果。

让我们看看该怎样设置一些简单的路由动画!

1、安装React

首先安装 React 并创建一个 React 应用程序,很简单的就能创建一个 React 项目并让它运行。

如果你还没有安装 Create React App 就先装好(如果你已经安装,就跳过这一步):

</>复制代码

  1. npm install -g create-react-app

然后创建我们的项目:

</>复制代码

  1. create-react-app animatedroutes && cd animatedroutes

接下来安装 routes 和 animation 包:

</>复制代码

  1. yarn add react-router-dom animated react-transition-group

现在用你喜欢的编辑器打开项目,并运行它:

</>复制代码

  1. npm start
2、添加 React 路由

打开 src/index.js 文件,给 React 添加 BrowserRouter

</>复制代码

  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import { BrowserRouter } from "react-router-dom";
  4. import App from "./App";
  5. import registerServiceWorker from "./registerServiceWorker";
  6. import "./index.css";
  7. ReactDOM.render(
  8. ,
  9. document.getElementById("root")
  10. );
  11. registerServiceWorker();

然后添加两个需要渲染的组建,首先是 src/Home.js :

</>复制代码

  1. import React, { Component } from "react";
  2. export default class Home extends Component {
  3. render() {
  4. return (
  5. Home

  6. Hello from the home page!

  7. )
  8. }
  9. }

接着是 src/Subpage.js:

</>复制代码

  1. import React, { Component } from "react";
  2. export default class Subpage extends Component {
  3. render() {
  4. return (
  5. Subpage

  6. Hello from a sub page!

  7. )
  8. }
  9. }

下面打开src/App.js 文件并修改内容为:

</>复制代码

  1. import React, { Component } from "react";
  2. import { Route, Link } from "react-router-dom";
  3. import Home from "./Home";
  4. import Subpage from "./Subpage";
  5. class App extends Component {
  6. render() {
  7. return (
  8. Home
  9. Subpage
  10. );
  11. }
  12. }
  13. export default App;

最后删除 src/App.css 的内容,并把下面的代码复制到src/index.css 文件中:

</>复制代码

  1. html,
  2. body,
  3. #root {
  4. height: 100%;
  5. width: 100%;
  6. }
  7. body {
  8. margin: 0;
  9. padding: 0;
  10. font-family: sans-serif;
  11. }
  12. .App {
  13. position: relative;
  14. display: flex;
  15. flex-flow: column;
  16. }
  17. .TopBar {
  18. position: fixed;
  19. top: 0;
  20. left: 0;
  21. display: flex;
  22. flex-flow: row nowrap;
  23. align-items: center;
  24. width: 100%;
  25. height: 62px;
  26. padding: 0 24px;
  27. }
  28. .TopBar a {
  29. margin-right: 18px;
  30. text-decoration: none;
  31. }
  32. .animated-page-wrapper {
  33. position: absolute;
  34. top: 62px;
  35. left: 0;
  36. width: 100%;
  37. height: 100%;
  38. }
  39. .page {
  40. padding: 0 24px;
  41. }

好了,现在可以通过路由在主页面和子页面之间进行导航了。

3、添加 TransitionGroup

现在开始添加动画效果。我们需要做一些微不足道的工作来实现它。

现在,我们不再用默认的方式设置路由,而是要使用路由渲染方法来去渲染前面的组件,并将其封装到一个中。

首先把TransitionGroup导入你的 src/App.js,像这样:

</>复制代码

  1. import TransitionGroup from "react-transition-group/TransitionGroup";

然后我们必须为 TransitionGroup 添加一个特殊的函数来渲染子组件。在 src/App.js 文件中class App extends ... 的前面添加这个函数:

</>复制代码

  1. const firstChild = props => {
  2. const childrenArray = React.Children.toArray(props.children);
  3. return childrenArray[0] || null;
  4. };

然后删除你的路由,并替换成下面的代码:

</>复制代码

  1. (
  2. {match && }
  3. )}/>
  4. (
  5. {match && }
  6. )}/>

您现在可以访问新的生命周期方法了,比如 componentWillAppear()componentWillEnter()componentWillLeave()

让我们用它们来制作一个更高级的组件来实现我的的动画路由效果,现在好戏开场了!

4、创建Animated Wrapper 并用 Animated 实现动画

创建src/AnimatedWrapper.js文件并复制下面的代码到文件中:

</>复制代码

  1. import React, { Component } from "react";
  2. import * as Animated from "animated/lib/targets/react-dom";
  3. const AnimatedWrapper = WrappedComponent => class AnimatedWrapper
  4. extends Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. animate: new Animated.Value(0)
  9. };
  10. }
  11. render() {
  12. return (
  13. );
  14. }
  15. };
  16. export default AnimatedWrapper;

这里有很多东西,我来解释一下。

我们用component来包装我们的路由组件。它将从 TransitionGroup 接收生命周期方法,我们可以用它来实现动画效果。
我们还用 Animated 创建了一个变量,可以用它来对封装的子组件中的 div 的不同样式属性实现动画效果。

让我们添加一些生命周期方法给组件添加动画效果。用Animated.template渲染,并且/或者插入动画状态值。

按照下面的代码修改src/AnimatedWrapper.js文件内容:

</>复制代码

  1. import React, { Component } from "react";
  2. import * as Animated from "animated/lib/targets/react-dom";
  3. const AnimatedWrapper = WrappedComponent => class AnimatedWrapper
  4. extends Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. animate: new Animated.Value(0)
  9. };
  10. }
  11. componentWillAppear(cb) {
  12. Animated.spring(this.state.animate, { toValue: 1 }).start();
  13. cb();
  14. }
  15. componentWillEnter(cb) {
  16. setTimeout(
  17. () => Animated.spring(this.state.animate, { toValue: 1 }).start(),
  18. 250
  19. );
  20. cb();
  21. }
  22. componentWillLeave(cb) {
  23. Animated.spring(this.state.animate, { toValue: 0 }).start();
  24. setTimeout(() => cb(), 175);
  25. }
  26. render() {
  27. const style = {
  28. opacity: Animated.template`${this.state.animate}`,
  29. transform: Animated.template`
  30. translate3d(0,${this.state.animate.interpolate({
  31. inputRange: [0, 1],
  32. outputRange: ["12px", "0px"]
  33. })},0)
  34. `
  35. };
  36. return (
  37. );
  38. }
  39. };
  40. export default AnimatedWrapper;

然后我们需要在每个路由组件中导入它,然后像这样将它们封装起来:

修改 src/Home.js 如下:

</>复制代码

  1. import React, { Component } from "react";
  2. import AnimatedWrapper from "./AnimatedWrapper";
  3. class HomeComponent extends Component {
  4. render() {
  5. return (
  6. Home

  7. Hello from the home page!

  8. )
  9. }
  10. }
  11. const Home = AnimatedWrapper(HomeComponent);
  12. export default Home;

修改 src/Subpage.js 如下:

</>复制代码

  1. import React, { Component } from "react";
  2. import AnimatedWrapper from "./AnimatedWrapper";
  3. class SubpageComponent extends Component {
  4. render() {
  5. return (
  6. Subpage

  7. Hello from a sub page!

  8. )
  9. }
  10. }
  11. const Subpage = AnimatedWrapper(SubpageComponent);
  12. export default Subpage;

就这样,现在你的页面切换效果应该是动态的了!

扩展阅读

我建议通过Animated文档来学习,但是现在相关文档很少。我们实用的Animated.template函数在 Github-issues 以外的地方几乎找不到。它的文档在这里:http://animatedjs.github.io/i...。
你可以通过下面的链接下载Demo的演示视频:
http://animate.mhaagens.me/
或者:
https://github.com/mhaagens/a...

也可以关注我在Medium的博客或者我的Twitter,来学习更多 React 相关的内容。
https://twitter.com/mhaagens

欢迎扫描二维码关注公众号,每天第一时间推送我翻译的国外最新技术文章。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84706.html

相关文章

  • 2017-08-08 前端日报

    摘要:前端日报精选一行代码的逆向工程译只需四个步骤使用实现页面过渡动画如何实现一个基于的模板引擎解剖组件的多种写法与演进深入理解笔记扩展对象的功能性中文基础系列一之实现抽奖刮刮卡橡皮擦掘金小游戏个人文章和最常用的特征众成翻译常用语法总 2017-08-08 前端日报 精选 一行 JavaScript 代码的逆向工程【译】只需四个步骤:使用 React 实现页面过渡动画如何实现一个基于 DOM...

    alin 评论0 收藏0
  • 一个App完成入门篇(二)-搭建主框架

    摘要:一个完成入门篇二搭建主框架通过第一课的学习,你已经掌握了如何通过调试器来跟上的设计器联调来实时查看设计效果调试代码了,接下来通过一系列的开发教学你将很快上手学习到如何开发一个真正的。 一个App完成入门篇(二)-搭建主框架 通过第一课的学习,你已经掌握了如何通过debug调试器来跟PC上的设计器联调来实时查看UI设计效果、调试代码了,接下来通过一系列的demo开发教学你将很快上手学习到...

    whatsns 评论0 收藏0
  • 一个App完成入门篇(二)-搭建主框架

    摘要:一个完成入门篇二搭建主框架通过第一课的学习,你已经掌握了如何通过调试器来跟上的设计器联调来实时查看设计效果调试代码了,接下来通过一系列的开发教学你将很快上手学习到如何开发一个真正的。 一个App完成入门篇(二)-搭建主框架 通过第一课的学习,你已经掌握了如何通过debug调试器来跟PC上的设计器联调来实时查看UI设计效果、调试代码了,接下来通过一系列的demo开发教学你将很快上手学习到...

    DevTalking 评论0 收藏0
  • 一个App完成入门篇(二)-搭建主框架

    摘要:一个完成入门篇二搭建主框架通过第一课的学习,你已经掌握了如何通过调试器来跟上的设计器联调来实时查看设计效果调试代码了,接下来通过一系列的开发教学你将很快上手学习到如何开发一个真正的。 一个App完成入门篇(二)-搭建主框架 通过第一课的学习,你已经掌握了如何通过debug调试器来跟PC上的设计器联调来实时查看UI设计效果、调试代码了,接下来通过一系列的demo开发教学你将很快上手学习到...

    maybe_009 评论0 收藏0
  • 正在失业中的《课多周刊》(第3期)

    摘要:正在失业中的课多周刊第期我们的微信公众号,更多精彩内容皆在微信公众号,欢迎关注。若有帮助,请把课多周刊推荐给你的朋友,你的支持是我们最大的动力。是一种祸害译本文浅谈了在中关于的不好之处。浅谈超时一运维的排查方式。 正在失业中的《课多周刊》(第3期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的...

    robin 评论0 收藏0

发表评论

0条评论

moven_j

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<