首先感谢崔学社
经过7天的学习跟着阿崔通过拆分任务,小步迭代,完成了一个mini-react,了解了Fiber、Reconcile等执行原理。
Day1
1. 实现最简 mini-react
在根目录下创建 
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>mini-react</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="main.js"></script>
  </body>
</html>
根目录下
// /main.js
import ReactDom from "./core/ReactDom.js";
import App from "./App.js";
ReactDom.createRoot(document.querySelector("#root")).render(App);
根目录下 
// /App.js
import React from "./core/React.js";
const App = React.createElement("div", { id: "app" }, "hello world");
export default App;
根目录下 
// /core/React.js
function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map((child) => {
        return typeof child === "string" ? createTextNode(child) : child;
      }),
    },
  };
};
{
  "type": "div",
  "props": {
      "id": "app",
      "children": [
          {
              "type": "TEXT_ELEMENT",
              "props": {
                  "nodeValue": "hello world",
                  "children": []
              }
          }
      ]
  }
}
render接收两个参数,el是通过createElement创建出来的,container就是dom节点。
通过
循环将props中key的值,对应赋值给dom[key]。
单独处理children,递归处理子节点。
function render(el, container) {
  const dom =
    el.type === "TEXT_ELEMENT"
      ? document.createTextNode("")
      : document.createElement(el.type);
  Object.keys(el.props).forEach((key) => {
    if (key !== "children") {
      dom[key] = el.props[key];
    }
  });
  const children = el.props.children;
  children.forEach((child) => {
    render(child, dom);
  });
  container.append(dom);
}
function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map((child) => {
        return typeof child === "string" ? createTextNode(child) : child;
      }),
    },
  };
};
function createTextNode(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: [],
    },
  };
};
function render(el, container) {
  const dom =
    el.type === "TEXT_ELEMENT"
      ? document.createTextNode("")
      : document.createElement(el.type);
  Object.keys(el.props).forEach((key) => {
    if (key !== "children") {
      dom[key] = el.props[key];
    }
  });
  const children = el.props.children;
  children.forEach((child) => {
    render(child, dom);
  });
  container.append(dom);
}
const React = {
  render,
  createElement,
};
export default React;
根目录下 
import React from "./React.js";
const ReactDom = {
  createRoot(container) {
    return {
      render(App) {
        return React.render(App, container);
      },
    };
  },
};
export default ReactDom;
在根目录通过

到这里我们就实现了最简版本
2. 引入vite,使用JSX
在根目录下创建vite项目
pnpm create vite vite-runner --template vanilla
将之前的
将
// /vite-runner/main.jsx
import ReactDom from "./core/ReactDom.js";
import App from "./App.jsx";
ReactDom.createRoot(document.querySelector("#root")).render(App);
别忘了修改
... <div id="root"></div> <script type="module" src="/main.jsx"></script> ...
这样我们就可以通过vite启动项目了,别忘了在vite-runner下安装依赖
cd vite-runner pnpm dev
仓库地址:https://github.com/zhuzhux/mini-react