首页 > 其他分享 >01 | JSX 代码是如何“摇身一变”成为 DOM 的?

01 | JSX 代码是如何“摇身一变”成为 DOM 的?

时间:2022-12-28 15:00:53浏览次数:39  
标签:01 key DOM JSX source propName props config children

JSX 的本质是什么

JSX 是 JavaScript 的一种语法扩展,它和模板语言很接近,但是它充分具备 JavaScript 的能力,JSX 的本质是React.createElement这个 JavaScript 调用的语法糖。

JSX 是如何映射为 DOM

1. JSX 标签都被Babel转化成了 React.createElement 调用;

2. createElement 执行到最后会 return 一个针对 ReactElement 的调用;

3. ReactElement 把传入的参数按照一定的规范,“组装”进了 element 对象里,这个 ReactElement 对象实例,本质上是以 JavaScript 对象形式存在的对 DOM 的描述,也就是“虚拟 DOM”;

4. 通过ReactDOM.render最终渲染到DOM容器中;

如下图:

 

 

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

createElement

入参:type、config、children;

出参:针对 ReactElement 的调用 

函数体拆解:

1.特殊处理React 元素的属性key、ref、self、source ‘

2.遍历config ,提取属性到props;

3.提取子元素,推到props.children;

4.格式化defaultProps;

5.返回ReactElement 的调用 ;

如下图:

代码:

/**

 101. React的创建元素方法

 */

export function createElement(type, config, children) {

  // propName 变量用于储存后面需要用到的元素属性

  let propName; 

  // props 变量用于储存元素属性的键值对集合

  const props = {}; 

  // key、ref、self、source 均为 React 元素的属性,此处不必深究

  let key = null;

  let ref = null; 

  let self = null; 

  let source = null; 



  // config 对象中存储的是元素的属性

  if (config != null) { 

    // 进来之后做的第一件事,是依次对 ref、key、self 和 source 属性赋值

    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 里面的属性都一个一个挪到 props 这个之前声明好的对象里面

    for (propName in config) {

      if (

        // 筛选出可以提进 props 对象里的属性

        hasOwnProperty.call(config, propName) &&

        !RESERVED_PROPS.hasOwnProperty(propName) 

      ) {

        props[propName] = config[propName]; 

      }

    }

  }

  // childrenLength 指的是当前元素的子元素的个数,减去的 2 是 type 和 config 两个参数占用的长度

  const childrenLength = arguments.length - 2; 

  // 如果抛去type和config,就只剩下一个参数,一般意味着文本节点出现了

  if (childrenLength === 1) { 

    // 直接把这个参数的值赋给props.children

    props.children = children; 

    // 处理嵌套多个子元素的情况

  } else if (childrenLength > 1) { 

    // 声明一个子元素数组

    const childArray = Array(childrenLength); 

    // 把子元素推进数组里

    for (let i = 0; i < childrenLength; i++) { 

      childArray[i] = arguments[i + 2];

    }

    // 最后把这个数组赋值给props.children

    props.children = childArray; 

  } 



  // 处理 defaultProps

  if (type && type.defaultProps) {

    const defaultProps = type.defaultProps;

    for (propName in defaultProps) { 

      if (props[propName] === undefined) {

        props[propName] = defaultProps[propName];

      }

    }

  }



  // 最后返回一个调用ReactElement执行方法,并传入刚才处理过的参数

  return ReactElement(

    type,

    key,

    ref,

    self,

    source,

    ReactCurrentOwner.current,

    props,

  );

}

 

标签:01,key,DOM,JSX,source,propName,props,config,children
From: https://www.cnblogs.com/superlizhao/p/17010144.html

相关文章