react的jsx和React.createElement是什么关系?面试常问

news2024/11/27 14:43:08

1、JSX

在React17之前,我们写React代码的时候都会去引入React,并且自己的代码中没有用到,这是为什么呢?

这是因为我们的 JSX 代码会被 Babel 编译为 React.createElement,我们来看一下babel的表示形式。

image.png

需要注意的是:

  • 自定义组件时需要首字母用大写,会被识别出是一个组件,这是一个规定。
  • 小写默认会认为是一个html标签,编译成字符串。

image.png

结论:JSX 的本质是React.createElement这个 JavaScript 调用的语法糖。是JS的语法扩展

2、React.createElement源码阅读

从上面我们知道jsx通过babel编译成React.createElement,下面我们就去看一下相关源码:

2.1 入参解读

入参解读:创造一个元素需要知道哪些信息

export function createElement(type, config, children)

createElement 有 3 个入参,这 3 个入参囊括了 React 创建一个元素所需要知道的全部信息。

  • type:用于标识节点的类型。它可以是类似“h1”“div”这样的标准 HTML 标签字符串,也可以是 React 组件类型或 React fragment 类型。
  • config:以对象形式传入,组件所有的属性都会以键值对的形式存储在 config 对象中。
  • children:以对象形式传入,它记录的是组件标签之间嵌套的内容,也就是所谓的“子节点”“子元素”。
React.createElement("ul", {
  // 传入属性键值对
  className: "list"
   // 从第三个入参开始往后,传入的参数都是 children
}, React.createElement("li", {
  key: "1"
}, "1"), React.createElement("li", {
  key: "2"
}, "2"));

对应的DOM结构

<ul className="list">
  <li key="1">1</li>
  <li key="2">2</li>
</ul>

从入口文件React.js文件可知,React.createElement方法是从ReactElement文件引入进来的,我们就进入这个文件,定位到createElement方法。

image.png

2.1.1 先来看config参数的处理

// 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]; 
      }
    }
  }

参考 前端进阶面试题详细解答

这段代码对 ref 以及 key 做了个验证处理,具体如何验证我们先不关心,从方法名称上来辨别一下,然后遍历 config 并把属性提进 props 对象里。

const RESERVED_PROPS = {
  key: true,
  ref: true,
  __self: true,
  __source: true,
};

也就是把ref和key剔除。

2.1.2 接下来是一段对于 children 的操作

// 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; 
  } 

首先把第二个参数之后的参数取出来,然后判断长度是否大于一。大于一的话就代表有多个 children,这时候 props.children 会是一个数组,否则的话只是一个对象。

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

// 最后返回一个调用ReactElement执行方法,并传入刚才处理过的参数
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );

2.1.4 处理传入的defaultProps

image.png

// 处理 defaultProps
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) { 
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }

2.2 小结

createElement 中并没有十分复杂的涉及算法或真实 DOM 的逻辑,它的每一个步骤几乎都是在格式化数据。

3、出参解读

image.png 上面已经分析过,createElement 执行到最后会 return 一个针对 ReactElement 的调用。

3.1 ReactElement源码拆解

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // REACT_ELEMENT_TYPE是一个常量,用来标识该对象是一个ReactElement
    $$typeof: REACT_ELEMENT_TYPE,

    // 内置属性赋值
    type: type,
    key: key,
    ref: ref,
    props: props,

    // 记录创造该元素的组件
    _owner: owner,
  };

  // 
  if (__DEV__) {
    // 这里是一些针对 __DEV__ 环境下的处理,对于大家理解主要逻辑意义不大,此处我直接省略掉,以免混淆视听
  }

  return element;
};

$$typeof 来帮助我们识别这是一个 ReactElement

3.2 小结

ReactElement 其实只做了一件事情就是组装数据。

可以在React中尝试打印:

const AppJSX = (<div className="App">
  <h1 className="title">I am the title</h1>
  <p className="content">I am the content</p>
</div>)

console.log(AppJSX)

得到的控制台结果: image.png

这个 ReactElement 对象实例,本质上是以 JavaScript 对象形式存在的对 DOM 的描述,也就是虚拟 DOM

3.3 扩展知识

既然是虚拟 DOM,就意味着和渲染到页面上的真实 DOM 不是一个东西,那就需要用ReactDOM.render方法来渲染真实DOM。

ReactDOM.render(
    // 需要渲染的元素(ReactElement)
    element, 
    // 元素挂载的目标容器(一个真实DOM)
    container,
    // 回调函数,可选参数,可以用来处理渲染结束后的逻辑
    [callback]
)

ReactDOM.render 方法可以接收 3 个参数,其中第二个参数就是一个真实的 DOM 节点,这个真实的 DOM 节点充当“容器”的角色,React 元素最终会被渲染到这个“容器”里面去。比如,示例中的 App 组件,它对应的 render 调用是这样的:

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kotlin 原生拓展函数与非拓展函数

先看一下图文 根据定义的性质可分为两类 非拓展函数 repeat 循环函数,可使用该函数执行一些有限循环任务,务必在构造函数传入循环次数 repeat(repeatNumber:Int 1) with 条件补充区域,可在某些需要两个或者多个函数对象直接的属性进行依赖操作时使用 …

Python 读取图像方式总结

读取并显示图像 opencv3库scikit-image库PIL库读取图像结果分析 打印图像信息 skimage获取图像信息PIL获取图像信息 读取并显示图像方法总结 PIL库读取图像Opencv3读取图像scikit-image库读取图像参考资料 学习数字图像处理&#xff0c;第一步就是读取图像。这里我总结下如何…

深度学习——CPU,GPU,TPU等硬件说明(笔记)

目录 深度学习硬件&#xff1a;CPU和GPU 深度学习硬件&#xff1a;TPU 深度学习硬件&#xff1a;CPU和GPU 1.提升CPU的利用率Ⅰ&#xff1a;提升空间和时间的内存本地性 ①在计算ab之前&#xff0c;需要准备数据 主内存->L3->L2->L1->寄存器 L1&#xff1a;访…

【LeetCode每日一题:1697. 检查边长度限制的路径是否存在~~~并查集+数组排序+排序记录下标位置】

题目描述 给你一个 n 个点组成的无向图边集 edgeList &#xff0c;其中 edgeList[i] [ui, vi, disi] 表示点 ui 和点 vi 之间有一条长度为 disi 的边。请注意&#xff0c;两个点之间可能有 超过一条边 。 给你一个查询数组queries &#xff0c;其中 queries[j] [pj, qj, li…

抖音商家引流的正确方法,抖音商家引流脚本实操教程。

大家好我是你们的小编一辞脚本&#xff0c;今天给大家分享新的知识&#xff0c;很开心可以在CSDN平台分享知识给大家,很多伙伴看不到代码我先录制一下视频 在给大家做代码&#xff0c;给大家分享一下抖音商家引流脚本的知识和视频演示 不懂的小伙伴可以认真看一下&#xff0c…

【lssvm回归预测】基于遗传算法优化最小二乘支持向量机GA-lssvm实现数据回归预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

图书商城小程序开发,实现图书便捷式选购

1995年联合国教文组织将4月23日规定为世界读书日&#xff0c;由此可见对全世界人民来说读书都是一件很重要的事。并且据调查数据显示&#xff0c;去年我国成年国民图书阅读量达到了59.7%&#xff0c;同比增长了0.2个百分点&#xff1b;人均纸质图书阅读量为4.76&#xff0c;较上…

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

问题背景 需求背景 需求&#xff1a;对商品的上架与下架进行管控&#xff0c;下架的商品不能进行销售 上架与下架的管控&#xff0c;在我负责的项目&#xff08;单据系统&#xff09;中实现&#xff1b;销售的控制则是在另外一个项目&#xff08;POS系统&#xff09;中实现的…

人工智能课后作业_python实现广度优先遍历搜索(BFS)(附源码)

2 广度优先遍历搜索(BFS) 2.1算法介绍2.2实验代码2.3实验结果2.4实验总结 2.1算法介绍 广度优先搜索算法&#xff08;英语&#xff1a;Breadth-First-Search&#xff0c;缩写为BFS&#xff09;&#xff0c;是一种图形搜索算法。简单的说&#xff0c;BFS是从根节点开始&#…

MATLAB动态导入文件功能(txt文件读入)

目录 一、界面搭建 1.axes坐标轴 2.LIST表 3.button按钮 二、属性 三、代码实现 一、界面搭建 1.axes坐标轴 需要有一个可以显示点的axes&#xff0c;以及一个展示点坐标XYZ的LIST表控件 2.LIST表 LIST需要添加表头&#xff0c;XYZ&#xff0c;行1,2,3,4,.. 右键列表…

降本增效: 蚂蚁在 Sidecarless 的探索和实践

文&#xff5c;王发康 &#xff08;花名&#xff1a;毅松 &#xff09; 蚂蚁集团技术专家、MOSN 项目核心开发者 深耕于高性能网络服务器研发&#xff0c;目前专注于云原生 ServiceMesh、Nginx、MOSN、Envoy、Istio 等相关领域。 本文 5574 字 阅读 14 分钟 前言 从单体到分…

三、数据链路层(二)封装成帧和透明传输

目录 2.1字符计数法 2.2字符填充的首尾定界符法 2.3零比特填充的首尾标志法 2.4违规编码法 组帧就是一段数据的前后分别添加首部和尾部&#xff0c;确定帧的界限。 组帧的目的是解决帧定界、帧同步&#xff08;接收方应能从接收到的二进制比特流中区分出帧的起始和终止&am…

java计算机毕业设计ssm智能交通信息管理平台6w258(附源码、数据库)

java计算机毕业设计ssm智能交通信息管理平台6w258&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

气象数据相关分析及使用系列:基于CALMET诊断模型的高时空分辨率精细化风场模拟

【查看原文】气象数据相关分析及使用系列&#xff1a;基于CALMET诊断模型的高时空分辨率精细化风场模拟技术应用​​​​​​ 在研究流场时&#xff0c;常用观测、模型风洞测试和数值模拟方法进行研究。但时常遇到研究区气象站点分布稀疏&#xff0c;不能代表周边复杂地形的风场…

PHP session相关知识详解

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是PHP session相关知识详解。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未…

JavaScript 版文章自动创建目录导航菜单控件源代码,用来生成文章导航,可生成独立的侧边栏导航菜单

特点 支持 UMD 规范&#xff1b;拥有 AnchorJS 基础功能&#xff1b;支持中文和英文标题文字生成ID&#xff1b;支持生成独立的侧边栏导航菜单&#xff1b;支持直接在文章中生成文章导读导航&#xff1b;自动分析标题关系&#xff0c;生成段落层级索引值&#xff1b;可以作为 …

试着开发一个Pagination组件

1 组件需求和模块设计 我们要实现的分页组件大致效果如下&#xff1a; 组件需求 点击左右分页按钮可以跳转到上一页/下一页&#xff1b;点击中间的页码按钮可以跳转到相应的页码&#xff1b;首页尾页需要始终显示出来&#xff08;如果只有1页则不显示尾页&#xff09;&#x…

数字孪生助力油气管道行业实现资产管理

随着数字孪生技术的发展日臻成熟&#xff0c;各个行业领域都在经历一场翻天覆地的变化。结合国内的油气管网系统建设现状&#xff0c;数字孪生技术对油气管道行业数智化建设必将有重大而深远的意义。 数字孪生助力油气管道行业实现资产管理 北京智汇云舟科技有限公司成立于201…

【发表案例】2/3区计算机视觉类SCI,3个月19天录用

2/3区计算机视觉类SCI 【期刊简介】IF:2.5-3.0&#xff0c;JCR2/3区&#xff0c;中科院4区 【检索情况】SCI 在检&#xff0c;正刊 【征稿领域】面向智能交通应用的物联网驱动计算机视觉技术 录用案例&#xff1a;3个月19天录用 2022.12.05 | Accepted 2022.11.17 | Edit…

全新的 React 组件设计理念 Headless UI

其实&#xff0c;最早接触 Headless UI 是在去年&#xff0c;碰巧看到了一个非常前沿且优秀的组件库 ---- Chakra UI&#xff0c;这个组件库本身就是 Headless UI 的实践者&#xff0c;同时也是 CSS-IN-JS 的集大成者。 我当时看过之后&#xff0c;就对该理念产生了很大的兴趣…