欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

react 学习之路一 --JSX

程序员文章站 2022-03-22 10:20:06
JSX 的本质是什么,它和 JS 之间到底是什么关系?为什么要用 JSX?不用会有什么后果?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

以上就是今天要分享的全部内容了,感谢阅读。一起努力吧。共勉

本文地址:https://blog.****.net/weixin_40548203/article/details/109242341

相关标签: react js