从0实现React18

270 阅读2分钟

Screenshot 2023-05-01 at 11.09.40 AM.png 仓库链接 课程链接

JSX转换是什么

jsx转换playground

什么是jsx

JSX是一种JavaScript语法扩展,通常用于在React应用程序中定义UI组件。JSX允许您在JavaScript代码中编写类似HTML的标记,以描述应该如何渲染UI组件。

使用JSX,您可以在JavaScript代码中创建类似于以下的代码片段:

const element = <h1>Hello, world!</h1>;

这段代码会被编译成以下的JavaScript代码:

const element = React.createElement("h1", null, "Hello, world!");

这个React.createElement()函数调用将生成一个虚拟DOM元素,该元素可以被React用来更新实际的DOM元素。JSX让编写React组件变得更加直观和易于阅读,因为您可以使用熟悉的HTML标记来描述UI的外观和行为。 实现jsx代码 Before react v17

import { TEXT, ELEMENT } from './constants';
import { ReactElement } from './vdom';

function createElement(type, config = {}, ...children) {
    delete config.__source;
    delete config.__self;
    let { key, ref, ...props } = config;
    let $$typeof = null;
    if (typeof type === 'string') {
        $$typeof = ELEMENT;
    }
    props.children = children.map(item => typeof item === 'object' || typeof item === 'function' ? item
        : { $$typeof: TEXT, type: TEXT, content: item });
    return ReactElement($$typeof, type, key, ref, props);
}

const React = {
    createElement
}
export default React;

After react v17 ``

export const jsx = (type: ElementType, config: any, ...maybeChildren: any) => {
	let key: Key = null;
	const props: Props = {};
	let ref: Ref = null;

	for (const prop in config) {
		const val = config[prop];
		if (prop === 'key') {
			if (val !== undefined) {
				key = '' + val;
			}
			continue;
		}
		if (prop === 'ref') {
			if (val !== undefined) {
				ref = val;
			}
			continue;
		}
		if ({}.hasOwnProperty.call(config, prop)) {
			props[prop] = val;
		}
	}
	const maybeChildrenLength = maybeChildren.length;
	if (maybeChildrenLength) {
		if (maybeChildrenLength === 1) {
			props.children = maybeChildren[0];
		} else {
			props.children = maybeChildren;
		}
	}
		return ReactElement(type, key, ref, props);

调试打包流程

image.png

reconciler的工作方式

对于同一个节点,比较其ReactElementfiberNode,生成子fiberNode。并根据比较的结果生成不同标记(插入、删除、移动......),对应不同宿主环境API的执行。

image.png 比如,挂载<div></div>

// React Element <div></div>
jsx("div")
// 对应fiberNode
null
// 生成子fiberNode
// 对应标记
Placement

<div></div>更新为<p></p>

// React Element <p></p>
jsx("p")
// 对应fiberNode
FiberNode {type'div'}
// 生成子fiberNode
// 对应标记
Deletion Placement

当所有ReactElement比较完后,会生成一棵fiberNode树,一共会存在两棵fiberNode树

  • current:与视图中真实UI对应的fiberNode树
  • workInProgress:触发更新后,正在reconciler中计算的fiberNode树

双缓冲技术介绍

image.png 先整理笔记到此 日后有时间在更新