通过课程和博客学习react,能够应付平时的开发工作。但到了面试等环节,对于fiber,setState的同步异步问题,说是知道,但往往朝深处一问,结合实际做一些输出题,脑袋里往往没有清晰的脉络,所以我决定自己实现一份miniReact,提升自己对react的理解。
本文大部分内容都是从历史好文build your own react中参考借鉴,这确实是我看到的最好的学习react的文章,在这里表示感谢。
准备工作
首先新启一个项目
csharp
npm init
npm i vite
简单配置vite.config.js

新建入口文件index.html,引入index.js

现在我们的准备工作就完成了。
一,jsx
jsx是一个语法糖,在编译后其实是使用了createElement函数。所以我们第一步就是实现createElement用于创建虚拟dom。我们miniReact只关心部分使用到的属性,不做完全详尽的处理。
(面试点,为什么老版本的react需要在顶部引入react,而新版本不需要)
现在,我们先从hello world开始
ini
const rootDOM = document.getElementById("root");
const element = createElement("div", null, "hello world");
render(element, rootDOM);
接下来我们需要依次实现createElement用于创建虚拟dom,以及render用于将虚拟dom渲染到界面上。
简化版的虚拟dom需要三个参数,分别是type,props,以及children。
1.1 createElement
typescript
const createElement = (type, props, ...children) => {
return {
type,
props: {
...props,
children: children.map((child) => (typeof child === "object" ? child : createTextElement(child))),
},
};
};
function createTextElement(text) {
return {
type: "TEXT_ELEMENT",
props: {
nodeValue: text,
children: [],
},
};
}
1.2 render
ini
function render(element, container) {
const dom =
element.type == "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type)
const isProperty = key => key !== "children"
Object.keys(element.props)
.filter(isProperty)
.forEach(name => {
dom[name] = element.props[name]
})
element.props.children.forEach(child =>
render(child, dom)
)
container.appendChild(dom)
}
恭喜我们完成了第一步,成功的将一个虚拟dom渲染到了界面上,虽然简单,但是开始比什么都重要!

1.3 测试
接下来让我们做一些简单的测试
ini
const elementList = Array.from({ length: 100 }, (_, i) => {
const key = `Item-${i}`;
return createElement("li", { key }, key);
});
const element = createElement("ul", null, ...elementList);
render(element, rootDOM);
将渲染的dom给得多一些,就可以看到很明显的卡顿,在此期间界面没法操作,这就是react fiber架构要解决的主要问题。
