• React源码分析1-jsx转换及React.createElement


    jsx 的转换

    我们从 react 应用的入口开始对源码进行分析,创建一个简单的 hello, world 应用:

    import React, {
        Component } from 'react';
    import ReactDOM from 'react-dom';
    export default class App extends Component {
       
      render() {
       
        return <div>hello, world</div>;
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们注意到,我们在 App 组件中直接写了 return

    hello, world
    的 jsx 语句,那么 jsx 语法是如何被浏览器识别执行的呢?

    另外我在第一次学习 react 的时候,就有一个疑惑: import React, { Component } from 'react' 这段代码中,React 似乎在代码中没有任何地方被用到,为什么要引入呢?

    16.x 版本及之前

    我们在 react16.8 版本的代码中,尝试将 React 的引用去掉:

    // import React, { Component } from 'react';
    import {
        Component } from 'react'; // 去掉 React 的引用
    import ReactDOM from 'react-dom';
    
    export default class App extends Component {
       
      render() {
       
        return <div>hello, world</div>;
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行应用程序,发现会提示 'React' must be in scope when using JSX 的 error:

    这是因为上述的类组件 render 中返回了

    hello, world
    的 jsx 语法,在React16版本及之前,应用程序通过 @babel/preset-react 将 jsx 语法转换为 React.createElement 的 js 代码,因此需要显式将 React 引入,才能正常调用 createElement。我们可以在 Babel REPL 中看到 jsx 被 @babel/preset-react 编译后的结果

    17.x 版本及之后

    React17版本之后,官方与 bbel 进行了合作,直接通过将 react/jsx-runtime 对 jsx 语法进行了新的转换而不依赖 React.createElement,转换的结果便是可直接供 ReactDOM.render 使用的 ReactElement 对象。因此如果在React17版本后只是用 jsx 语法不使用其他的 react 提供的api,可以不引入 React,应用程序依然能够正常运行。

    更多有关于 React jsx 转换的内容可以去看官网了解:介绍全新的JSX转换,在这里就不再过多展开了。

    React.createElement 源码

    虽然现在 react17 之后我们可以不再依赖 React.createElement 这个 api 了,但是实际场景中以及很多开源包中可能会有很多通过 React.createElement 手动创建元素的场景,所以还是推荐学习一下React.createElement源码。

    React.createElement 其接收三个或以上参数:

    • type:要创建的 React 元素类型,可以是标签名称字符串,如 'div' 或者 'span' 等;也可以是 React组件 类型(class组件或者函数组件);或者是 React fragment 类型。
    • config:写在标签上的属性的集合,js 对象格式,若标签上未添加任何属性则为 null。
    • children:从第三个参数开始后的参数为当前创建的React元素的子节点,每个参数的类型,若是当前元素节点的 textContent 则为字符串类型;否则为新的 React.createElement 创建的元素。

    函数中会对参数进行一系列的解析,源码如下,对源码相关的理解都用注释进行了标记:

    export function createElement(type, config, children) {
       
      let propName;<
    • 1
    • 2
  • 相关阅读:
    【人见人爱报错系列】GIt常见问题解决大全
    〖Python WEB 自动化测试实战篇⑮〗 实战 - 自动化测试的持续集成
    计数排序【java实现】
    Linux云服务环境安装-Nginx篇
    Springboot视图渲染技术
    零代码编程:用ChatGPT将SRT字幕文件批量转为Word文本文档
    2.python之变量
    python基础 | 类与继承
    web分析-手把手教你怎么写小程序事件分析
    学习ASP.NET Core Blazor编程系列五——列表页面
  • 原文地址:https://blog.csdn.net/It_kc/article/details/127400350