ReactDOMTreeTraversal

ReactDOMTreeTraversal模块通过ReactDefaultInjection模块添加为EventPluginUtils模块的ComponentTree,供react合成事件对象获取_dispatchListeners、_dispatchInstances绑定回调函数及组件实例使用。

 

// ReactDOMTreeTraversal模块通过ReactDefaultInjection模块添加为EventPluginUtils模块的ComponentTree
// 供react合成事件对象获取_dispatchListeners、_dispatchInstances绑定回调函数及组件实例使用
'use strict';

var _prodInvariant = require('./reactProdInvariant');

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

// 获取组件实例instA、instB所共有的同个祖先组件实例
function getLowestCommonAncestor(instA, instB) {
  !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
  !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;

  var depthA = 0;
  for (var tempA = instA; tempA; tempA = tempA._hostParent) {
    depthA++;
  }
  var depthB = 0;
  for (var tempB = instB; tempB; tempB = tempB._hostParent) {
    depthB++;
  }

  // instA的层级比instB低,向上获取同instB平级的、instA的祖先组件
  while (depthA - depthB > 0) {
    instA = instA._hostParent;
    depthA--;
  }

  while (depthB - depthA > 0) {
    instB = instB._hostParent;
    depthB--;
  }

  // 获取共有的祖先组件实例
  var depth = depthA;
  while (depth--) {
    if (instA === instB) {
      return instA;
    }
    instA = instA._hostParent;
    instB = instB._hostParent;
  }

  // instA、instB不是由同一个祖先组件实例绘制,返回null
  return null;
}

// 判断组件实例instA是否为instB的父组件
function isAncestor(instA, instB) {
  !('_hostNode' in instA) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;
  !('_hostNode' in instB) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;

  while (instB) {
    if (instB === instA) {
      return true;
    }
    instB = instB._hostParent;
  }
  return false;
}

// 获取父组件
function getParentInstance(inst) {
  !('_hostNode' in inst) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;

  return inst._hostParent;
}

// 向上获取inst的直系父组件,执行fn函数,以获取该父组件的冒泡、捕获阶段的绑定回调函数
function traverseTwoPhase(inst, fn, arg) {
  var path = [];
  while (inst) {
    path.push(inst);
    inst = inst._hostParent;
  }
  var i;
  for (i = path.length; i-- > 0;) {
    fn(path[i], 'captured', arg);
  }
  for (i = 0; i < path.length; i++) {
    fn(path[i], 'bubbled', arg);
  }
}

// 参数argFrom鼠标移开状态的SyntheticMouseEvent类合成事件对象
// 参数argTo鼠标进入状态的SyntheticMouseEvent类合成事件对象
// 参数from鼠标移开的react组件实例
// 参数to鼠标进入的react组件实例
// 向上获取from的直系父组件(直到与to共有的祖先组件位置),执行fn,以获取该父组件绑定的鼠标离开事件的回调函数
// 向上获取to的直系父组件(直到与from共有的祖先组件位置),执行fn,以获取该父组件绑定的鼠标移入事件的回调函数
function traverseEnterLeave(from, to, fn, argFrom, argTo) {
  var common = from && to ? getLowestCommonAncestor(from, to) : null;
  var pathFrom = [];
  while (from && from !== common) {
    pathFrom.push(from);
    from = from._hostParent;
  }
  var pathTo = [];
  while (to && to !== common) {
    pathTo.push(to);
    to = to._hostParent;
  }
  var i;
  for (i = 0; i < pathFrom.length; i++) {
    fn(pathFrom[i], 'bubbled', argFrom);
  }
  for (i = pathTo.length; i-- > 0;) {
    fn(pathTo[i], 'captured', argTo);
  }
}

module.exports = {
  // isAncestor(instA,instB)判断组件实例instA是否为instB的父组件
  isAncestor: isAncestor,

  // getLowestCommonAncestor(instA,instB)获取组件实例instA、instB所共有的同个祖先组件实例
  getLowestCommonAncestor: getLowestCommonAncestor,

  // getParentInstance(inst)获取父组件
  getParentInstance: getParentInstance,

  // traverseTwoPhase(inst,fn,arg)遍历inst的直系父组件,执行fn函数,以获取该父组件的冒泡、捕获阶段的绑定回调函数
  traverseTwoPhase: traverseTwoPhase,

  // traverseEnterLeave(from,to,fn,argFrom,argTo)
  // 遍历rom的直系父组件(直到与to共有的祖先组件位置),执行fn,以获取该父组件绑定的鼠标离开事件的回调函数
  // 遍历to的直系父组件(直到与from共有的祖先组件位置),执行fn,以获取该父组件绑定的鼠标移入事件的回调函数
  traverseEnterLeave: traverseEnterLeave
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值