React源码解析18(1)------ React.createElement 和 jsx

1.React.createElement

我们知道在React17版本之前,我们在项目中是一定需要引入react的。

import React from "react"

即便我们有时候没有使用到React,也需要引入。原因是什么呢?

在React项目中,如果我们使用了模板语法JSX,我们知道它要先经过babel的转译。那babel会将JSX转换成什么样子的格式呢?

可以看到,现在的babel会将JSX模板转换成带有jsx方法的内容。但是在17之前,babel是将JSX转换为带有React.createElement方法的内容。

而这也是为什么在17之前我们要引入React才能让项目正常使用。

2.ReactElement元素

如果我们在项目代码中,打印一个react元素:

javascript 复制代码
const jsx = <div><span>123</span></div>
console.log(jsx)

可以在控制台看到:

所以我们通过babel转译后的内容,执行完应该生成这样的一个ReactElement对象。

所以在实现jsx方法前,我们可以定义一个ReactElement类(实际的React源码中是一个方法,但是这里为了好看一些,使用类的结构)。

javascript 复制代码
class ReactElement {
  constructor(key, props, ref, type) {
    this.$$typeof = Symbol.for('react.element')
    this.key = key;
    this.props = props;
    this.ref = ref;
    this.type = type;
  }
}

3.实现JSX方法

在上面的转译内容我们可以看到,jsx方法接受两个参数,第一个参数是类型:例如div,span或者自定一类型。

第二个参数是配置参数:例如class,ref等参数。

我们只需要将ref,type,key这三个属性,直接赋值给ReactElement元素。而其他的属性全部放在props里面就可以了:

javascript 复制代码
function jsx(type, config) {
  let key, props = {}, ref;
  for(let propName in config){
    if(propName === 'key'){
      key = config[propName];
    }else if(propName === 'ref'){
      ref = config[propName];
    }else {
      props[propName] = config[propName]
    }
  }
  return new ReactElement(key,props,ref,type)
}

由于递归的过程已经被babel处理了,所以其实在jsx方法中只需要遍历即可,并不需要太过复杂的处理。

4.测试

现在我们使用babel转译过的内容,对jsx方法进行测试:

javascript 复制代码
const reactElement = jsx("div", {
  ref: "123",
  style: {
    color: 'red'
  },
  children: ["123", jsx("span", {
    children: "456"
  })]
});

console.log(reactElement)

可以在控制台看到jsx方法执行的结果:

以上就是通过babel处理后,react对处理的内容做的初步处理。

相关推荐
小高0072 分钟前
React useMemo 深度指南:原理、误区、实战与 2025 最佳实践
前端·javascript·react.js
LuckySusu12 分钟前
【js篇】深入理解类数组对象及其转换为数组的多种方法
前端·javascript
LuckySusu12 分钟前
【js篇】数组遍历的方法大全:前端开发中的高效迭代
前端·javascript
LuckySusu13 分钟前
【js篇】for...in与 for...of 的区别:前端开发中的迭代器选择
前端·javascript
mon_star°18 分钟前
有趣的 npm 库 · json-server
前端·npm·json
去伪存真1 小时前
手把手教你实现用AI大模型做代码审查
前端·人工智能
科粒KL1 小时前
前端学习笔记- 从 HTTP 1.1 到 3,再从 SSE 到 Streamable HTTP
前端·http
盘子素1 小时前
前端实现有校验的大文件下载方案对比
前端
一颗奇趣蛋1 小时前
React.memo & useMemo:为什么 React 里「看起来没变的组件」还是渲染了
前端·react.js
天蓝色的鱼鱼1 小时前
Vue项目多级路径部署终极指南:基于环境变量的统一配置方案
前端·vue.js·架构