ReactEventListener

ReactEventListener模块通过ReactDefaultInjection模块加载为ReactBrowserEventEmitter模块的ReactEventListener属性,提供的功能是react方式监听节点事件,在事件回调中执行ReactEventListener.dispatchEvent方法——构建合成事件对象、并执行该系列合成事件对象的绑定回调,当存在脏组件时,重绘组件。

 

'use strict';

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

// 用于绑定非捕获类或捕获类事件,返回值用于解绑事件
var EventListener = require('fbjs/lib/EventListener');

var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
var PooledClass = require('./PooledClass');

// 由组件实例获取节点;或者由节点获取组件实例
var ReactDOMComponentTree = require('./ReactDOMComponentTree');

// ReactUpdates.batchedUpdates执行回调,存在脏组件时,重绘组件
var ReactUpdates = require('./ReactUpdates');

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

// 获取滚动时的偏移量
var getUnboundedScrollPosition = require('fbjs/lib/getUnboundedScrollPosition');

// 调用组件挂载在ReactDom.render生成的元素container下,findParent查询由ReactDom.render生成的父级组件
function findParent(inst) {
  while (inst._hostParent) {
    inst = inst._hostParent;
  }
  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
  var container = rootNode.parentNode;
  return ReactDOMComponentTree.getClosestInstanceFromNode(container);
}

// 该实例作为handleTopLevelImpl函数的参数,传递原生事件、事件名
// 参数topLevelType为事件名,nativeEvent为原生事件对象
function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
  this.topLevelType = topLevelType;
  this.nativeEvent = nativeEvent;
  this.ancestors = [];
}
_assign(TopLevelCallbackBookKeeping.prototype, {
  destructor: function () {
    this.topLevelType = null;
    this.nativeEvent = null;
    this.ancestors.length = 0;
  }
});
PooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);

// 构建合成事件对象,并执行合成事件对象中的绑定回调函数
function handleTopLevelImpl(bookKeeping) {
  // nativeEventTarget为触发事件的节点元素
  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);

  // 由触发节点元素获取最近的reactDomComponent实例
  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);

  var ancestor = targetInst;
  do {
    bookKeeping.ancestors.push(ancestor);
    ancestor = ancestor && findParent(ancestor);
  } while (ancestor);

  for (var i = 0; i < bookKeeping.ancestors.length; i++) {
    targetInst = bookKeeping.ancestors[i];

    // 构建合成事件对象,并执行该对象的绑定回调函数_dispatchListeners
    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
  }
}

function scrollValueMonitor(cb) {
  var scrollPosition = getUnboundedScrollPosition(window);
  cb(scrollPosition);
}

// react方式监听节点事件,绑定ReactEventListener.dispatchEvent派发事件方法,回调中构建合成事件对象并执行合成事件对象绑定回调的
var ReactEventListener = {
  _enabled: true,
  _handleTopLevel: null,

  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,

  // 通过ReactDefaultInjection模块赋值_handleTopLevel=ReactEventEmitterMixin.handleTopLevel
  setHandleTopLevel: function (handleTopLevel) {
    ReactEventListener._handleTopLevel = handleTopLevel;
  },

  // 是否允许派发react事件,即在组件重绘后调用合成事件对象的绑定回调函数
  setEnabled: function (enabled) {
    ReactEventListener._enabled = !!enabled;
  },

  // 判断是否允许派发react事件
  isEnabled: function () {
    return ReactEventListener._enabled;
  },

  // 冒泡方式绑定事件,回调设为ReactEventListener.dispatchEvent,构建合成事件对象并执行该对象的回调
  trapBubbledEvent: function (topLevelType, handlerBaseName, element) {
    if (!element) {
      return null;
    }
    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
  },

  // 捕获方式绑定事件,回调设为ReactEventListener.dispatchEvent,构建合成事件对象并执行该对象的回调
  trapCapturedEvent: function (topLevelType, handlerBaseName, element) {
    if (!element) {
      return null;
    }
    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
  },

  // 监听滚动事件,滚动时执行refresh回调,传参为滚动偏移量
  monitorScrollValue: function (refresh) {
    var callback = scrollValueMonitor.bind(null, refresh);
    EventListener.listen(window, 'scroll', callback);
  },

  // 在浏览器事件发生时,构建合成事件对象,并调用合成事件对象的绑定回调;若回调中导致state改变,则重绘组件
  dispatchEvent: function (topLevelType, nativeEvent) {
    // 判断是否允许派发react事件,不允许则返回
    if (!ReactEventListener._enabled) {
      return;
    }

    // 创建bookKeeping实例,为handleTopLevelImpl回调函数传递事件名和原生事件对象
    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);
    try {
      // 执行handleTopLevelImpl,若存在state改变引起的脏组件时,重绘组件
      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
    } finally {
      // 清空bookKeeping实例数据
      TopLevelCallbackBookKeeping.release(bookKeeping);
    }
  }
};

module.exports = ReactEventListener;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值