【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...

相关推荐
goldenocean2 小时前
React之旅-05 List Key
前端·javascript·react.js
杨进军4 小时前
React 实现节点删除
前端·react.js·前端框架
爱编程的喵4 小时前
React useContext 深度解析:告别组件间通信的噩梦
前端·react.js
赫本的猫6 小时前
告别生命周期!用Hooks实现更优雅的React开发
前端·react.js·面试
赫本的猫6 小时前
React中的路由艺术:用react-router-dom实现无缝页面切换
前端·react.js·面试
光影少年6 小时前
React 组件中怎么做事件代理?它的原理是什么?
前端·react.js·掘金·金石计划
燃烧的土豆6 小时前
React 18 全局错误捕获 + React-router 6 动态权限路由
javascript·react.js·webpack
杨进军6 小时前
React 实现 useReducer
前端·react.js·前端框架
徐小夕6 小时前
开源了一款基于Nextjs实现的精美CRM系统, 卷王程序员狂喜!
前端·react.js·github