深刻浅出React核心源码解析(1) jsx与babel的背后

1、引言

这一系列的文章我会尽我所能,用扁平化的思惟,和合理顺序来帮助你们分析React究竟是怎么玩的,但仍要假定读者具有最基础的开发经验与知识储备,具体的条件以下:javascript

  • 开发过至少一个基于react的完整项目。
  • 熟悉标准js基础。
  • 了解适当的设计模式
  • 了解适当的数据结构,起码要知道什么是栈,什么是队列。

只要能知足上述的条件,那么这个系列就是适合你阅读的。html

2、jsx的背后

你们可能都知道,使用create-react-app建立出的项目能够直接在js文件里书写react组件,或者jsx代码。java

好比:react

const com = <div>12332</div>
    console.log(com);

复制代码

像上面的代码,通过create-react-app自带的webpack编译事后,能够成功在浏览器中执行。当咱们把这段代码复制出到浏览器窗口里,咱们会发现控制台报错了。webpack

很简单,由于原生js并不支持jsx语法,也就是说,标准的js运行环境中,是不容许写html标签的,js中没有这样的语法。之因此代码跑的起来,是由于通过了babel的编译。web

在当下,jsx代码多数是由@babel/preset-react转译而成。设计模式

咱们能够打开babel的playground查看一下背后都发生了些什么。数组

能够看到,实际上在浏览器中的跑的代码实际上是以下一段:浏览器

 "use strict";

var com = React.createElement("div", null, "123123");

复制代码

能够这样试一下,js中的代码<div>123123</div>其实相等于React.createElement("div", null, "123123")bash

3、props

createElement这个方法,有两个必填参数,和无限剩余可选参数,第一个参数是元素的名称(字符串或者是其余类型),或者是其余类型(后面会讲),第二个参数就是你们熟知的props。

咱们如今给div加个属性上去

const com = <div id="123">123123</div>
复制代码

编译后

var com = React.createElement("div", {
  id: "123"
}, "123123");
复制代码

能够发现,第二个参数在没有任何prop属性的状况下,是个null,可只要传入了任意一个props,就会变成一个plainObject,好比上面的{id:"123"}

至于第二个参数之后,参数的数量是零到无限的,就是该元素的直系children有多少个,后续就会有多少个参数,也是createElement方法的嵌套,咱们再看下嵌套下的状况。

const com = <div id="123"><span>1</span><span>2</span></div>
复制代码
var com = React.createElement("div", 
    {
        id: "123"
    }, 
    React.createElement("span", null, "1"), 
    React.createElement("span", null, "2")
);

复制代码

看的出,div元素下的两个span也被转换成了createElement而且被依次排列在了第二个参数后面。

这就是babel之力,平时咱们写的大部分标签语法,实际最后都转成了这个样子。createElement应该是最高频被调用的内置方法了。

4、函数组件和类组件呢?

function AComp() {
    return <div>123</div>
}

const a = <AComp/>
复制代码
"use strict";

function AComp() {
  return React.createElement("div", null, "123");
}

var a = React.createElement(AComp, null);
复制代码

咱们能够看到<Acomp>被转换成了React.createElement(AComp, null);。这个时候咱们传入的第一个参数不是字符串了,而是使用的函数组件自己。

把AComp从函数改为类组件,也会有相同的结果,具体的逻辑判断,会在react-dom中体现,这个咱们后面再说。

5、组件为何必定要大写开头

那咱们如今把AComp改为小写的名字,改成acomp。

function acomp() { return <div />}

const a = <acomp/>

复制代码
"use strict";

function acomp() {
  return React.createElement("div", null);
}

// 第一个参数是字符串"acomp",而非acomp函数自己
var a = React.createElement("acomp", null);

复制代码

babel编译后之后能够看得出,createElement的第一个参数并非acomp这个函数自己了,而是一个字符串,preset-react会把全部小写开头的标签,转换为字符串,它人为小写开头的元素声明,都是原生dom元素,好比div。而大写开头的就是函数组件或者类组件。

而当咱们把组件写成小写调用后,就会没法调用确切想调用的组件。

六 本章总结

搞懂了jsx和Babel是咋回过后,下一节咱们来分析createElement是怎么回事,他的背后到底都作了些啥子东西。

相关文章
相关标签/搜索