`

ReactTransitionGroup

 
阅读更多

ReactTransitionGroup模块通过ReactWithAddons模块提供外部接口,还被ReactCSSTransitionGroup模块调用;用于操控子节点componentWillAppear等方法的执行时机,以及由上层组件提供的childFactory方法劫持渲染子节点。

 

'use strict';

var _assign = require('object-assign');

// 构造函数作为普通函数调用报错
function _classCallCheck(instance, Constructor) { 
  if (!(instance instanceof Constructor)) { 
    throw new TypeError("Cannot call a class as a function"); 
  } 
}

function _possibleConstructorReturn(self, call) { 
  if (!self) { 
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 
  } 
  return call && (typeof call === "object" || typeof call === "function") ? call : self; 
}

// 继承
function _inherits(subClass, superClass) { 
  if (typeof superClass !== "function" && superClass !== null) { 
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 
  } 
  subClass.prototype = Object.create(superClass && superClass.prototype, 
    { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); 
  if (superClass) Object.setPrototypeOf ? 
    Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 
}

var React = require('./React');

// getChildMapping方法将props.children扁平化处理
// mergeChildMappings方法将前后两次已经扁平化的数据props.children复合为一
var ReactTransitionChildMapping = require('./ReactTransitionChildMapping');

var emptyFunction = require('fbjs/lib/emptyFunction');

var ReactTransitionGroup = function (_React$Component) {
  _inherits(ReactTransitionGroup, _React$Component);

  function ReactTransitionGroup() {
    var _temp, _this, _ret;

    _classCallCheck(this, ReactTransitionGroup);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (
      _this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), 
      
      // 将props.children扁平化后赋值给this.state
      // 在组件的componentDidAppear生命周期中,state.children包含前后两次props.children的所有子节点
      // 通过更新后的props.children判断state.children中的某个节点是否移除,触发该子节点componentWillLeave方法,及更新state
      _this.state = {
        children: ReactTransitionChildMapping.getChildMapping(_this.props.children)
      },

      // componentDidMount生命周期内执行,子节点一经挂载,即执行子组件的componentWillAppear、componentDidAppear方法
      _this.performAppear = function (key) {
        _this.currentlyTransitioningKeys[key] = true;

        var component = _this.refs[key];

        if (component.componentWillAppear) {
          component.componentWillAppear(_this._handleDoneAppearing.bind(_this, key));
        } else {
          // 子节点没有componentWillAppear方法,调用_handleDoneAppearing执行子节点的componentDidAppear方法
          // 当子节点componentDidAppear方法内促使ReactTransitionGroup的props.children删除该子节点时,调用performLeave
          // 何种代码书写方式下发生???
          _this._handleDoneAppearing(key);
        }
      }, 

      // 作为子节点componentWillAppear方法的回调,触发子节点的componentDidAppear方法
      // 当子节点componentWillAppear方法内促使ReactTransitionGroup的state.children不再包含该子节点时,调用performLeave
      _this._handleDoneAppearing = function (key) {
        var component = _this.refs[key];
        if (component.componentDidAppear) {
          component.componentDidAppear();
        }

        delete _this.currentlyTransitioningKeys[key];

        var currentChildMapping = ReactTransitionChildMapping.getChildMapping(_this.props.children);

        if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
          _this.performLeave(key);
        }
      }, 

      // 组件props.children新增子节点引起重绘时,componentDidUpdate生命周期内触发performEnter方法
      _this.performEnter = function (key) {
        _this.currentlyTransitioningKeys[key] = true;

        var component = _this.refs[key];

        if (component.componentWillEnter) {
          component.componentWillEnter(_this._handleDoneEntering.bind(_this, key));
        } else {
          _this._handleDoneEntering(key);
        }
      }, 
      _this._handleDoneEntering = function (key) {
        var component = _this.refs[key];
        if (component.componentDidEnter) {
          component.componentDidEnter();
        }

        delete _this.currentlyTransitioningKeys[key];

        var currentChildMapping = ReactTransitionChildMapping.getChildMapping(_this.props.children);

        if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
          _this.performLeave(key);
        }
      }, 

      // 组件props.children删除子节点引起重绘时,componentDidUpdate生命周期内触发performLeave方法
      // 最终删除时,调用setState方法移除state.children中的该节点
      _this.performLeave = function (key) {
        _this.currentlyTransitioningKeys[key] = true;

        var component = _this.refs[key];
        if (component.componentWillLeave) {
          component.componentWillLeave(_this._handleDoneLeaving.bind(_this, key));
        } else {
          _this._handleDoneLeaving(key);
        }
      }, 
      _this._handleDoneLeaving = function (key) {
        var component = _this.refs[key];

        if (component.componentDidLeave) {
          component.componentDidLeave();
        }

        delete _this.currentlyTransitioningKeys[key];

        var currentChildMapping = ReactTransitionChildMapping.getChildMapping(_this.props.children);

        if (currentChildMapping && currentChildMapping.hasOwnProperty(key)) {
          _this.performEnter(key);
        } else {
          _this.setState(function (state) {
            var newChildren = _assign({}, state.children);
            delete newChildren[key];
            return { children: newChildren };
          });
        }
      }, _temp), _possibleConstructorReturn(_this, _ret);
  }

  ReactTransitionGroup.prototype.componentWillMount = function componentWillMount() {
    this.currentlyTransitioningKeys = {};// 以键值对形式记录子节点的componentWillAppear等方法执行过程中信息
    this.keysToEnter = [];// 存储组件props变更引起重绘时的新增子节点key值
    this.keysToLeave = [];// 存储组件props变更引起重绘时的删除子节点key值
  };

  ReactTransitionGroup.prototype.componentDidMount = function componentDidMount() {
    var initialChildMapping = this.state.children;
    for (var key in initialChildMapping) {
      if (initialChildMapping[key]) {
        this.performAppear(key);
      }
    }
  };

  // props变更时,state.children存储props.children变更前后的两份扁平化数据
  // this.keysToEnter | keysToLeave存储props.children中增或删的子节点key值
  ReactTransitionGroup.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    var nextChildMapping = ReactTransitionChildMapping.getChildMapping(nextProps.children);
    var prevChildMapping = this.state.children;

    // 将props.children变更前后的两份扁平化数据存入this.state.children
    // 通过componentDidUpdate生命周期内执行的performLeave方法剔除已删除的子节点
    this.setState({
      children: ReactTransitionChildMapping.mergeChildMappings(prevChildMapping, nextChildMapping)
    });

    var key;

    // props.children更新前没有key,更新后有key,将key推入this.keysToEnter
    for (key in nextChildMapping) {
      var hasPrev = prevChildMapping && prevChildMapping.hasOwnProperty(key);
      if (nextChildMapping[key] && !hasPrev && !this.currentlyTransitioningKeys[key]) {
        this.keysToEnter.push(key);
      }
    }

    // props.children更新后没有key,更新前有key,将key推入this.keysToLeave
    for (key in prevChildMapping) {
      var hasNext = nextChildMapping && nextChildMapping.hasOwnProperty(key);
      if (prevChildMapping[key] && !hasNext && !this.currentlyTransitioningKeys[key]) {
        this.keysToLeave.push(key);
      }
    }
  };

  // 依照props.children的增减项执行performEnter以及performLeave方法
  ReactTransitionGroup.prototype.componentDidUpdate = function componentDidUpdate() {
    var keysToEnter = this.keysToEnter;
    this.keysToEnter = [];
    keysToEnter.forEach(this.performEnter);

    var keysToLeave = this.keysToLeave;
    this.keysToLeave = [];
    keysToLeave.forEach(this.performLeave);
  };

  ReactTransitionGroup.prototype.render = function render() {
    // 设置ReactTransitionGroup的refs引用各子节点
    var childrenToRender = [];
    for (var key in this.state.children) {
      var child = this.state.children[key];
      if (child) {
        childrenToRender.push(React.cloneElement(this.props.childFactory(child), { ref: key, key: key }));
      }
    }

    var props = _assign({}, this.props);
    delete props.transitionLeave;
    delete props.transitionName;
    delete props.transitionAppear;
    delete props.transitionEnter;
    delete props.childFactory;
    delete props.transitionLeaveTimeout;
    delete props.transitionEnterTimeout;
    delete props.transitionAppearTimeout;
    delete props.component;

    // props.component作为容器节点
    // props.children扁平化后添加为ReactTransitionGroup的refs引用,作为props.component容器的子节点
    return React.createElement(this.props.component, props, childrenToRender);
  };

  return ReactTransitionGroup;
}(React.Component);

ReactTransitionGroup.displayName = 'ReactTransitionGroup';
ReactTransitionGroup.propTypes = {
  component: React.PropTypes.any,// 子节点的容器
  childFactory: React.PropTypes.func// 劫持渲染子节点的函数
};
ReactTransitionGroup.defaultProps = {
  component: 'span',
  childFactory: emptyFunction.thatReturnsArgument
};

// 操控子节点componentWillAppear等方法的执行时机,以及由上层组件提供的childFactory方法劫持渲染子节点
module.exports = ReactTransitionGroup;

 

0
0
分享到:
评论

相关推荐

    react-jest-issue:演示我在 ReactJest 设置中遇到的问题

    但是如果我们不这样做,我们会得到另一个错误,因为组件 B(组件 A 的子组件)被ReactTransitionGroup并且缺少ReactTransitionGroup注入的componentWillEnter等方法。 (我们无法模拟组件 B,但该测试设置的整个...

    react-transition-group-learning:使用React转换组和anime.js

    React过渡小组学习 了解React Transition Group和Anime.js 博客

    pyzmq-23.1.0-cp310-cp310-musllinux_1_1_x86_64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    MAVEN 教程和详细讲解

    MAVEN 教程和讲解

    人工智能基础知识背诵(大学生期末)

    人工智能基础知识背诵(大学生期末)

    pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    grpcio-1.23.0-cp37-cp37m-win_amd64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    算法部署-基于OpenVINO+Python部署YOLOv9目标检测算法-附项目源码+一键执行-优质项目实战.zip

    算法部署_基于OpenVINO+Python部署YOLOv9目标检测算法_附项目源码+一键执行_优质项目实战

    debian armhf系统opencv安装依赖包包含libjasper libtiff5 libjpeg

    libjasper1_1.900.1-debian1-2.4+deb8u6_armhf.deb libjasper-dev_1.900.1-debian1-2.4+deb8u6_armhf.deb libjpeg62-turbo_1.3.1-12+deb8u2_armhf.deb libjpeg62-turbo-dev_1%3a1.5.2-2+deb10u1_armhf.deb libjpeg-dev_1%3a1.5.2-2+deb10u1_all.deb libtiff5_4.1.0+git191117-2~deb10u9_armhf.deb libtiff5-dev_4.1.0+git191117-2~deb10u9_armhf.deb 找了好久终于找齐了,不容易

    Celery库,Python的邮递员

    Celery是一个开源的分布式任务队列系统,用于在后台执行异步任务,常在需要大规模消息处理的Web应用中使用。以下是Celery库的介绍: ### Celery库介绍 #### 1. 基本概念 - **Celery**: 一个基于Python的分布式任务队列,用于执行异步后台任务。 - **任务队列**: 一种用于管理和执行任务的系统,可以提高应用的响应性和可扩展性。 #### 2. 主要特点 - **异步执行**: 允许任务在后台异步执行,不阻塞主线程。 - **分布式**: 支持跨多个worker节点分布任务。 - **可扩展性**: 易于扩展以处理大量任务。 - **可靠性**: 支持任务重试机制,确保任务最终被执行。 #### 3. 核心组件 - **任务(Task)**: 后台执行的函数或方法。 - **Worker**: 负责执行任务的进程。 - **Broker**: 中间人,消息代理,用于接收和转发任务消息。常见的Broker有RabbitMQ和Redis。 - **结果后端**: 用于存储任务执行结果的系统,如数据库或Redis。

    07杯型基础工程.doc

    07杯型基础工程

    采样热网络,用于计算轴承温度matlab代码.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    树状数组简介及基础教程及特点阐述.rar

    树状数组树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述.rar树状数组简介及基础教程及特点阐述

    PHP语言教程&简单案例

    PHP语言案例简介: 本案例提供了一个使用PHP语言编写的简单Web页面程序,目的是展示如何在Web页面上输出"Hello, World!"。这个程序是PHP编程的基础示例,适合初学者作为学习PHP语言和Web开发的起点。 - **语言特性**: PHP是一种服务器端脚本语言,特别适用于创建动态Web页面和Web应用程序。 - **程序结构**: 程序结合了HTML和PHP代码,HTML负责页面结构,PHP负责服务器端逻辑和动态内容输出。 - **主要功能**: 程序运行后,在Web浏览器中显示一个包含"Hello, World!"文本的页面。 - **适用人群**: 适合对Web开发感兴趣的初学者,以及希望快速了解PHP编程基础的开发者。 - **学习价值**: 通过这个案例,学习者可以了解PHP的基本语法、如何在Web页面中嵌入PHP代码、以及如何通过PHP输出内容到Web页面。 - **运行方式**: 需要将PHP代码保存为`.php`文件,并在支持PHP的服务器上运行,通过Web浏览器访问结果。 - **环境搭建**: 需要安装PHP解释器和配置Web服务器(如

    pyzmq-25.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    海伦约会测试集data-test.txt

    海伦约会测试集data-test.txt

    软件工程(本科课程)期末考试速成

    内含基本考试大纲、试题、模拟题和知识点总结,帮助考前巩固速成。如有和课件或课本内容不符之处,请酌情参考,以本校讲解为重。文件或有疏漏,请留言更改,前人栽树功德无量。

    1717775450954003_order-blog.xhtml

    1717775450954003_order-blog.xhtml

    grpcio-1.24.3-cp37-cp37m-win_amd64.whl

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    基于springboot+vue的古典舞在线交流平台的设计与实现+mysql数据库脚本(高分毕业设计).zip

    本项目是一套基于SpringBoot+Vue的古典舞在线交流平台的设计与实现,搭配MySQL数据库脚本。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者。包含:项目源码、数据库脚本、项目说明等,有论文参考,该项目可以直接作为毕设使用。 技术实现方面,后台框架采用SpringBoot,数据库选用MySQL,开发环境包括JDK、IDEA和Tomcat。所有项目都经过严格调试,确保可以运行!如果基础还行,可以在此代码基础之上进行改动以实现更多功能。博主可有偿提供毕设相关的技术支持,非诚勿扰。 该平台旨在为用户提供一个专业的古典舞交流与分享空间,功能涵盖用户注册登录、发布舞蹈视频、评论互动、点赞收藏以及个人中心管理等。通过这些功能,用户可以方便地分享自己的舞蹈作品,欣赏他人的表演,并与其他舞蹈爱好者进行互动交流。 总之,这是一个非常实用的古典舞在线交流平台,无论是对于舞蹈爱好者还是计算机专业的学生来说都具有很高的参考价值和使用价值。运行测试ok,毕业设计、课程设计高分资源,放心下载使用!

Global site tag (gtag.js) - Google Analytics