react 学习之路一 --JSX

用了react一年,很多东西用的也是迷迷糊糊的,这里报了来自于拉钩教育的修言老师的课程来系统的学习一下react。下面算是我对于课程的笔记记录以及自我的一点理解吧。在此作出记录以及分享。如果想要一起加入学习之路的可以 点击这里 或者下面评论里说出来~ 共勉!

本节主要围绕JSX这三大问题来讲JSX:

1. JSX 的本质是什么,它和 JS 之间到底是什么关系?
2. 为什么要用 JSX?不用会有什么后果?
3. JSX 背后的功能模块是什么,这个功能模块都做了哪些事情?

首先:

  • JSX 的本质是什么,它和 JS 之间到底是什么关系?

JSX的本质是遵循以一定逻辑结构的 JS形式来描述的DOM节点。它其实就是JS,你可以把它理解为一个对象,然后react准备了一套规则(或者说标准(毕竟如果没有规则不好辨认敌友呀是吧))。是遵循reactDom描述的一个对象。就好像下面这个对象是我用来描述张三的一个对象。我知道这个规则是干嘛的,最后用我自己的东西把我的描述给"画"出来:

cosnt obj={
	name:"张三",
	val:"zs",
	item:{
	   ...balabala
	}
}
  • 为什么要用 JSX?不用会有什么后果?

JSX解析出来是React.createElement方法(不信去babel官网吧JSX复制上去看看)。如果用React.createElement方法的话,代码会很冗长,也不像JSX那样长的像html,不利于维护

  • JSX 背后的功能模块是什么,这个功能模块都做了哪些事情?

一个平常的JSX:

<div>我是一个JSX</div>

解析出来是:

React.createElement("div", null, "\u6211\u662F\u4E00\u4E2AJSX");

然后React.createElement又做了什么呢?

function createElement(type, config, children) {       var propName;
      //提取保留名称
      var props = {};

      var key = null;
      var ref = null;
      var self = null;
      var source = null;
      //标签的属性不为空时 说明标签有属性值 特殊处理:把key和ref赋值给单独的变量
      if (config != null) {
        //有合理的ref
        if (hasValidRef(config)) {
          ref = config.ref;
        }
        //有合理的key 
        if (hasValidKey(config)) {
          key = '' + config.key;
        }

        self = config.__self === undefined ? null : config.__self;
        source = config.__source === undefined ? null : config.__source;

        //config中剩余属性,且不是原生属性(RESERVED_PROPS对象的属性),则添加到新props对象中
        for (propName in config) {
          if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
            props[propName] = config[propName]; //config去除key/ref 其他属性的放到props对象中
          }
        }
      }
      // Children can be more than one argument, and those are transferred onto
      // the newly allocated props object.
      //子元素数量(第三个参数以及之后参数都是子元素 兄弟节点)
      var childrenLength = arguments.length - 2; 

      if (childrenLength === 1) {
        props.children = children;
      } else if (childrenLength > 1) {
        var childArray = Array(childrenLength); //声明一个数组
        //依次将children push到数组中
        for (var i = 0; i < childrenLength; i++) {
          childArray[i] = arguments[i + 2];
        }

        {
          //冻结array 返回原来的childArray且不能被修改 防止有人修改库的核心对象 冻结对象大大提高性能
          if (Object.freeze) {
            Object.freeze(childArray);
          }
        }
        props.children = childArray; //父组件内部通过this.props.children获取子组件的值
      } 

      //为子组件设置默认值 一般针对的是组件      //class com extends React.component 则com.defaultProps获取当前组件自己的静态方法 
      if (type && type.defaultProps) { //如果当前组件中有默认的defaultProps则把当前组件的默认内容 定义到defaultProps中
        var defaultProps = type.defaultProps; 

        for (propName in defaultProps) { 
          if (props[propName] === undefined) { //如果父组件中对应的值为undefinde 则把默认值赋值赋值给props当作props的属性
            props[propName] = defaultProps[propName];
          }
        }
      }

      {
        //一旦ref或者key存在
        if (key || ref) {
          //如果type是组件的话
          var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
          if (key) {
            defineKeyPropWarningGetter(props, displayName);
          }

          if (ref) {
            defineRefPropWarningGetter(props, displayName);
          }
        }
      }

      //props:1.config的属性值 2.children的属性(字符串/数组)3.default的属性值
      return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
    }

注:此部分源码转载于 https://www.cnblogs.com/sunxiaopei/p/12205447.html

实际上就是整理了下传进来的参数,最后反回调用一个 ReactElement 方法,并把之前整理的参数传进去。

那ReactElement 方法又做了什么呢?下面是该方法的源码:

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE,

    // Built-in properties that belong on the element
    type: type,
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };

  if (__DEV__) {
    element._store = {};

    // To make comparing ReactElements easier for testing purposes, we make
    // the validation flag non-enumerable (where possible, which should
    // include every environment we run tests in), so the test framework
    // ignores it.
    Object.defineProperty(element._store, 'validated', {
      configurable: false,
      enumerable: false,
      writable: true,
      value: false,
    });
    // self and source are DEV only properties.
    Object.defineProperty(element, '_self', {
      configurable: false,
      enumerable: false,
      writable: false,
      value: self,
    });
    // Two elements created in two different places should be considered
    // equal for testing purposes and therefore we hide it from enumeration.
    Object.defineProperty(element, '_source', {
      configurable: false,
      enumerable: false,
      writable: false,
      value: source,
    });
    if (Object.freeze) {
      Object.freeze(element.props);
      Object.freeze(element);
    }
  }

  return element;
};

__DEV__状态先不管的会话,其实也就是把传进来的数据组装好再返回去就是了。
再由上层方法继续往上反。最后的结果是传进去的JSX返回了一个用JS描述的html结构。这,就是虚拟DOM

done.

下一篇:v15生命周期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值