【mini-react系列】一、createElement和render函数

前言

最近参加了 崔效瑞老师 的7天mini-react训练营,虽然每天工作很忙,但还是抽出一两个小时跟进学习,坚持了7天,还是得给坚持到最后的自己点个赞!

虽然之前没有接触过React的源码,但是通过学习任务的拆分,将复杂模块的任务拆分成一个个小任务,小步走实现,再逐步优化代码。

时间虽短,内容却不少。先开始浅浅地记录下我的学习成果,先起个好头,希望今年能顺利更新完这个系列,给2024的自己先立第一个flag!!

在这7天的mini-react训练营中,我学到了:

  • 实现createElementrender函数
  • 实现任务调度器requestIdleCallback
  • 实现简易的fiber
  • 实现functionComponent
  • 实现事件绑定
  • 实现props
  • 实现diff更新
  • 实现useState
  • 实现useEffect

话不多说,进入今天的主题,先开始React的初始化,实现createElementrender函数

createElement函数

createElement 函数是用于创建虚拟 DOM 元素的函数。它通常被 JSX 编译器所使用,用来将 JSX 语法转换为对 React.createElement 的调用。

js 复制代码
function createTextNode(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: [],
    },
  }
}

function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map((child) => {
        const isTextNode = typeof child === "string" || typeof child === "number"
        return isTextNode ? createTextNode(child) : child
      }),
    },
  }
}

createElement 函数接受三个参数:type 表示元素的类型(例如 'div'),props 表示元素的属性(例如 { className: 'my-class' }),以及 children 表示元素的子元素。在实现中,它返回一个包含 typeprops 属性的对象。

为了处理文本节点,我们还定义了 createTextNode 函数,它创建一个特殊的类型为 'TEXT_ELEMENT' 的对象,用于表示文本节点。

在实际使用中,React 会递归地处理这些虚拟 DOM 对象,最终将它们转换为实际的 DOM 元素并渲染到页面上。

注意: 上述代码只是一个简化版的实现,真实的 React 源码中应该更加复杂,并包含更多的功能和优化。

render函数

render 函数是 React 中用于将虚拟 DOM 渲染到实际 DOM 的核心函数。

js 复制代码
function render(el, container) {
  const dom = el.type === "TEXT_ELEMENT"
    ? document.createTextNode("")
    : document.createElement(el.type)

  // id class
  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)
}

render 函数接受两个参数:element 表示要渲染的虚拟 DOM 元素,container 表示要渲染到的实际 DOM 容器。

首先,根据虚拟 DOM 的类型创建对应的实际 DOM 元素(文本节点和普通元素分别处理)。然后,将虚拟 DOM 元素的属性设置到实际 DOM 元素上,遍历子元素并递归调用 render 函数。最后,将创建好的实际 DOM 元素添加到容器中。

导出render函数

ReactDom文件导出render函数之后, 调用ReactDOM.createRoot(element).render 函数。这样,就可以使用 React 的渲染功能了。

js 复制代码
import React from "./React.js"
const ReactDOM = {
  createRoot(container) {
    return {
      render(App) {
        React.render(App, container)
      },
    }
  },
}

export default ReactDOM

示例解析

简单的渲染代码

jsx 复制代码
function App() {
  return (
    <div>
      hello world, my mini react!
      <div>befend</div>
    </div>
  )
}

export default App;

节点创建的过程内容

渲染结果

小结

  • createElementrender 是 React 中用于构建和渲染界面的核心函数。
  • 通常,createElement 函数用于创建虚拟 DOM 元素,通常由 JSX 编译器转换 JSX 语法时调用。而 render 函数将虚拟 DOM 渲染到实际 DOM。

总的来说,createElement 用于创建虚拟 DOM 元素,而 render 用于将这些虚拟 DOM 元素渲染到实际 DOM 中,从而构建用户界面。

仓库传送门: github.com/Befend/mini...

相关推荐
September_ning3 小时前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人3 小时前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱0013 小时前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
Rattenking5 小时前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
熊的猫6 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
小牛itbull11 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress
FinGet1 天前
那总结下来,react就是落后了
前端·react.js
王解1 天前
Jest项目实战(2): 项目开发与测试
前端·javascript·react.js·arcgis·typescript·单元测试
AIoT科技物语2 天前
免费,基于React + ECharts 国产开源 IoT 物联网 Web 可视化数据大屏
前端·物联网·react.js·开源·echarts
初遇你时动了情2 天前
react 18 react-router-dom V6 路由传参的几种方式
react.js·typescript·react-router