ReactCSSTransitionGroupChild

ReactCSSTransitionGroupChild模块实现了ReactCSSTransitionGroup的子组件切换样式的机制,样式切换的时机由ReactTransitionGroup模块完成,具体为子组件挂载、从ReactCSSTransitionGroup组件中添加或移除时触发appear类样式持续props.appearTimeout时间。

 

'use strict';

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

// ReactAddonsDOMDependencies.getReactDOM()获取"react-dom"模块
var ReactAddonsDOMDependencies = require('./ReactAddonsDOMDependencies');

// 用于添加、移除、判断是否包含某个样式类,以及是否某个校验器
var CSSCore = require('fbjs/lib/CSSCore');

// 绑定或移除animationend、transitionend事件
var ReactTransitionEvents = require('./ReactTransitionEvents');

// 校验children是否单个reactElement节点并输出
var onlyChild = require('./onlyChild');

var TICK = 17;

var ReactCSSTransitionGroupChild = React.createClass({
  displayName: 'ReactCSSTransitionGroupChild',

  propTypes: {
    // name属性或者为字符串,作为样式类前缀,或者对象形式指派特定的样式类
    name: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.shape({
      enter: React.PropTypes.string,
      leave: React.PropTypes.string,
      active: React.PropTypes.string
    }), React.PropTypes.shape({
      enter: React.PropTypes.string,
      enterActive: React.PropTypes.string,
      leave: React.PropTypes.string,
      leaveActive: React.PropTypes.string,
      appear: React.PropTypes.string,
      appearActive: React.PropTypes.string
    })]).isRequired,

    // 赋值为true,组价被ReactTransitionGroup挂载、添加、移除时添加持续特定时间的样式类
    appear: React.PropTypes.bool,
    enter: React.PropTypes.bool,
    leave: React.PropTypes.bool,

    // 样式类持续时间
    appearTimeout: React.PropTypes.number,
    enterTimeout: React.PropTypes.number,
    leaveTimeout: React.PropTypes.number
  },

  // 参数finishCallback为ReactTransitionGroup模块设定的回调函数,负责更新ReactTransitionGroup组件的state
  transition: function (animationType, finishCallback, userSpecifiedDelay) {
    // ReactAddonsDOMDependencies.getReactDOM()获取"react-dom"模块
    var node = ReactAddonsDOMDependencies.getReactDOM().findDOMNode(this);

    if (!node) {
      if (finishCallback) {
        finishCallback();
      }
      return;
    }

    // 获取样式类
    var className = this.props.name[animationType] || this.props.name + '-' + animationType;
    var activeClassName = this.props.name[animationType + 'Active'] || className + '-active';
    var timeout = null;

    // 移除样式类,并解绑animationend、transitionend事件,执行finishCallback回调
    // finishCallback为ReactTransitionGroup模块设定的回调函数,负责更新ReactTransitionGroup组件的state
    // 也即样式类有效期为userSpecifiedDelay时间,如name+"-appear"、name+"-appear-active"有效到props.appearTimeout时间
    // 若name+"-appear"、name+"-appear-active"无anmation、transition样式,且设置props.appearTimeout,样式将维持有效,直到节点被移除
    var endListener = function (e) {
      if (e && e.target !== node) {
        return;
      }

      clearTimeout(timeout);

      CSSCore.removeClass(node, className);
      CSSCore.removeClass(node, activeClassName);

      ReactTransitionEvents.removeEndEventListener(node, endListener);

      if (finishCallback) {
        finishCallback();
      }
    };

    // 添加样式类
    CSSCore.addClass(node, className);

    // 使用this.classNameAndNodeQueue缓存node节点和activeClassName样式类,并激活activeClassName样式类
    this.queueClassAndNode(activeClassName, node);

    // userSpecifiedDelay时间或当即移除样式类className、activeClassName
    if (userSpecifiedDelay) {
      timeout = setTimeout(endListener, userSpecifiedDelay);
      this.transitionTimeouts.push(timeout);
    } else {
      ReactTransitionEvents.addEndEventListener(node, endListener);
    }
  },

  // 使用this.classNameAndNodeQueue缓存node节点和activeClassName样式类,并激活activeClassName样式类
  queueClassAndNode: function (className, node) {
    this.classNameAndNodeQueue.push({
      className: className,
      node: node
    });

    if (!this.timeout) {
      this.timeout = setTimeout(this.flushClassNameAndNodeQueue, TICK);
    }
  },

  // 激活所有node节点的对应activeClassName样式类
  flushClassNameAndNodeQueue: function () {
    if (this.isMounted()) {
      this.classNameAndNodeQueue.forEach(function (obj) {
        CSSCore.addClass(obj.node, obj.className);
      });
    }
    this.classNameAndNodeQueue.length = 0;
    this.timeout = null;
  },

  componentWillMount: function () {
    this.classNameAndNodeQueue = [];
    this.transitionTimeouts = [];
  },

  componentWillUnmount: function () {
    if (this.timeout) {
      clearTimeout(this.timeout);
    }
    this.transitionTimeouts.forEach(function (timeout) {
      clearTimeout(timeout);
    });

    this.classNameAndNodeQueue.length = 0;
  },

  // 参数done为ReactTransitionGroup模块设定的回调函数,负责当前元素被移除时更新ReactTransitionGroup组件的state
  // componentWillAppear方法的执行时机由ReactTransitionGroup模块设定,组件加载时执行
  componentWillAppear: function (done) {
    if (this.props.appear) {
      this.transition('appear', done, this.props.appearTimeout);
    } else {
      done();
    }
  },

  componentWillEnter: function (done) {
    if (this.props.enter) {
      this.transition('enter', done, this.props.enterTimeout);
    } else {
      done();
    }
  },

  componentWillLeave: function (done) {
    if (this.props.leave) {
      this.transition('leave', done, this.props.leaveTimeout);
    } else {
      done();
    }
  },

  render: function () {
    return onlyChild(this.props.children);
  }
});

// ReactTransitionGroup模块负责样式切换的时机,如子组件挂载、添加或移除时
// ReactCSSTransitionGroupChild模块用于实现子组件样式的切换机制,添加含有动画的样式,动画执行完成后移除
//    并执行ReactTransitionGroup模块所需的回调
module.exports = ReactCSSTransitionGroupChild;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值