本篇react教程是基于React18版本,对应的代码在gitee上。
一、简单介绍JSX
jsx是React的模板语法,允许你在JavaScript代码中写类似HTML的代码。
jsx的使用方法,类似于在javaScript里直接编写HTML,在打包的时候@babel/plugin-transform-react-jsx
会将jsx语法其解析为js对象。
下面这个是jsx模板语法:
function App() {
return <h1 class="test" key="122" >Hello World</h1>;
}
打包的时候会使用@babel/plugin-transform-react-jsx插件将jsx模板语法转为类object对象,下面分别是16.x和17.x使用babel打包后的结果。
在react 16.x
之前每一个jsx模板文件,都必须声明React,然后React会调用createElement方法将jsx语法最转化为虚拟dom:
React.createElement("h1", null, "hello", React.createElement("span", {
style: {
color: 'red'
}
}, "world"));
在react 17.x
之后每一个jsx模板文件了就不用声明import React from “react”,而是直接调用react/jsx-runtime将其转化为虚拟dom:
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
_jsxs("h1", {
children: ["hello", _jsx("span", {
style: {
color: 'red'
},
children: "world"
})]
});
无论是使用jsx还是createElement方法,它们的本质作用都是将jsx模板转为虚拟dom。这个对象主要有以下几个组成属性$$typeof、type、key、ref、props。如下图是转化后的虚拟dom结构:
二、简单实现jsx方法
我们只实现17.x的jsx方法。
前面我们已经理解了,jsx方法的作用就是将jsx模板语法转为虚拟dom的结构。
import hasOwnProperty from 'shared/hasOwnProperty';
import { REACT_ELEMENT_TYPE } from 'shared/ReactSymbols';
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true
}
function hasValidKey(config) {
return config.key !== undefined;
}
function hasValidRef(config) {
return config.ref !== undefined;
}
function ReactElement(type, key, ref, props) {
return {//这就是React元素,也被称为虚拟DOM
$$typeof: REACT_ELEMENT_TYPE,
type,//h1 span
key,//唯一标识
ref,//后面再讲,是用来获取真实DOM元素
props//属性 children,style,id
}
}
export function jsxDEV(type, config) {
debugger
let propName;//属性名
const props = {};//属性对象
let key = null;//每个虚拟DOM可以有一个可选的key属性,用来区分一个父节点下的不同子节点
let ref = null;//引入,后面可以通过这实现获取真实DOM的需求
if (hasValidKey(config)) {
key = config.key;
}
if (hasValidRef(config)) {
ref = config.ref;
}
for (propName in config) {
if (hasOwnProperty.call(config, propName)
&& !RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName]
}
}
return ReactElement(type, key, ref, props);
}
对于React源码来说,我们先记住,jsx模板语法转化为虚拟dom,后会将虚拟dom生成fiber进行处理。
去运行一下我的代码,可能理解更加深入。
三、总结
- 用户编写jsx模板语法
- 打包时使用babel解析jsx模板语法
- 解析后的代码,功能是,使用jsx方法进行调用,生成虚拟dom
下一篇我们开始学习fiber
结构