一、引言
这一系列的文章我会尽我所能,用扁平化的思维,和合理顺序来帮助大家分析React到底是怎么玩的,但仍要假定读者具备最基础的开发经验与知识储备,具体的条件如下:
- 开发过至少一个基于react的完整项目。
- 熟悉标准js基础。
- 了解适当的设计模式
- 了解适当的数据结构,起码要知道什么是栈,什么是队列。
只要能满足上述的条件,那么这个系列就是适合你阅读的。
二、jsx的背后
大家可能都知道,使用create-react-app创建出的项目可以直接在js文件里书写react组件,或者jsx代码。
比如:
const com =12332console.log(com);复制代码
像上面的代码,经过create-react-app自带的webpack编译过后,可以成功在浏览器中执行。当我们把这段代码复制出到浏览器窗口里,我们会发现控制台报错了。
很简单,因为原生js并不支持jsx语法,也就是说,标准的js运行环境中,是不允许写html标签的,js中没有这样的语法。之所以代码跑的起来,是因为经过了babel的编译。
在当下,jsx代码多数是由@babel/preset-react转译而成。
我们可以打开babel的playground查看一下背后都发生了些什么。
可以看到,实际上在浏览器中的跑的代码其实是如下一段:
"use strict";var com = React.createElement("div", null, "123123");复制代码
可以这样试一下,js中的代码<div>123123</div>
其实相等于React.createElement("div", null, "123123")
。
三、props
createElement这个方法,有两个必填参数,和无限剩余可选参数,第一个参数是元素的名称(字符串或者是其他类型),或者是其他类型(后面会讲),第二个参数就是大家熟知的props。
我们现在给div加个属性上去
const com =123123复制代码
编译后
var com = React.createElement("div", { id: "123"}, "123123");复制代码
可以发现,第二个参数在没有任何prop属性的情况下,是个null,可只要传入了任意一个props,就会变成一个plainObject,比如上面的{id:"123"}
。
至于第二个参数以后,参数的数量是零到无限的,就是该元素的直系children有多少个,后续就会有多少个参数,也是createElement方法的嵌套,我们再看下嵌套下的情况。
const com =1 2复制代码
var com = React.createElement("div", { id: "123" }, React.createElement("span", null, "1"), React.createElement("span", null, "2"));复制代码
看的出,div元素下的两个span也被转换成了createElement并且被依次排列在了第二个参数后面。
这就是babel之力,平时我们写的大部分标签语法,实际最后都转成了这个样子。createElement应该是最高频被调用的内置方法了。
四、函数组件和类组件呢?
function AComp() { return123}const a =复制代码
"use strict";function AComp() { return React.createElement("div", null, "123");}var a = React.createElement(AComp, null);复制代码
我们可以看到<Acomp>
被转换成了React.createElement(AComp, null);
。这个时候我们传入的第一个参数不是字符串了,而是使用的函数组件本身。
把AComp从函数改成类组件,也会有相同的结果,具体的逻辑判断,会在react-dom中体现,这个我们后面再说。
五、组件为什么一定要大写开头
那我们现在把AComp改成小写的名字,改为acomp。
function acomp() { return }const a =复制代码
"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是怎么回事,他的背后到底都做了些啥子东西。