愚墨的博客
  • 首页
  • 前端技术
  • 面试
只争朝夕不负韶华
  1. 首页
  2. 前端框架
  3. React
  4. 正文

createElement源码阅读

2019年02月07日 2591点热度 0人点赞 0条评论

起因

因为部门前端系统越来越多,为了项目稳定运行、统计汇总、及时定位线上bug,急需前端埋点系统,并且对项目代码侵入性越小越好。所以急需一套react透明埋点方式。

组件写法 函数组件和类组件两种形式常用形式,还有就是createElement的写法,多用于写一些类库或者UI组件库使用。且前两种打包的时候也会转成后者。

侵入性最小且能在全局作用,只能从react入手了。劫持一波createElement。so,让我们先来撸一波源码。

ReactElement.createElement = function (type, config, children) {
  var propName;

  // 用于存储后面的属性
  var props = {};

  var key = null; // 元素的key
  var ref = null;  // 元素的ref
  var self = null; 
  var source = null;

  if (config != null) {
    // 判断是否有ref,有就赋值一下
    if (hasValidRef(config)) {
      ref = config.ref;
    }
    // 同理
    if (hasValidKey(config)) {
      key = '' + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    // 把config里面的属性都一个一个挪到props中
    for (propName in config) {
      // 判断是不是原型链上的属性
      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
        props[propName] = config[propName];
      }
    }
  }

  // children 可能是一个也可能是多个
  var childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    // 只有一个children
    props.children = children;
  } else if (childrenLength > 1) {
    // 遍历一下,把children放到 childArray上
    var childArray = Array(childrenLength);
    for (var i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (process.env.NODE_ENV !== 'production') {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    // 把这个数组赋值给props.children
    props.children = childArray;
  }

  // 有type并且type有defaultProps属性 type是一个组件
  if (type && type.defaultProps) {
    var defaultProps = type.defaultProps;
    // 同样的遍历
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  if (process.env.NODE_ENV !== 'production') {
    if (key || ref) {
      if (typeof props.typeof === 'undefined' || props.typeof !== REACT_ELEMENT_TYPE) {
        var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
        if (key) {
          defineKeyPropWarningGetter(props, displayName);
        }
        if (ref) {
          defineRefPropWarningGetter(props, displayName);
        }
      }
    }
  }
  // props里面存的是config的属性值,然后还有children的属性
  // return一个 调用ReactElement执行方法,并传入刚才处理过的参数
  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
};

比较简单的代码,所以我们可以从props上入手,如果props上有onCLick属性的,那么我们就在onClick触发前调用我们的埋点方法。目测可行。 具体的埋点方案,下次再说。

标签: 暂无
最后更新:2020年09月07日

愚墨

保持饥渴的专注,追求最佳的品质

点赞
< 上一篇
下一篇 >

文章评论

取消回复

搜搜看看
历史遗迹
  • 2023年5月
  • 2022年9月
  • 2022年3月
  • 2022年2月
  • 2021年12月
  • 2021年8月
  • 2021年7月
  • 2021年5月
  • 2021年4月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年9月
  • 2020年7月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年1月
  • 2019年5月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年9月
  • 2018年3月
  • 2018年2月
  • 2018年1月
  • 2017年11月
  • 2017年7月
  • 2017年6月
  • 2017年3月
  • 2017年2月
  • 2017年1月
  • 2016年12月
  • 2016年11月
  • 2016年9月
  • 2016年8月
  • 2016年7月
  • 2016年6月
  • 2016年5月
  • 2016年4月
  • 2016年3月
  • 2016年2月
  • 2016年1月
  • 2015年12月
  • 2015年10月
  • 2015年9月
  • 2015年7月
  • 2015年6月
  • 2015年4月

COPYRIGHT © 2020 愚墨的博客. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS