实现一个mini-react

本文将介绍如何从React源码出发,理解其工作原理并实现一个简易版的React。主要内容包括React的Fiber结构、核心功能如createElement、render、updateDOM的实现,以及模拟useState Hook。通过删减官方源码,最终构建一个mini-react。
摘要由CSDN通过智能技术生成

首先 说下原理

react自v16以后发生了很多变化,v16以后底层的“虚拟DOM”不再是简单JSON数据了,React采用了最新的Fiber(双向链表)的数据结构,作为“协调”(Diff)运算的基础数据。React背后还提供了强大的 react-reconciler 和 scheduler 库实现Fiber链表的生成、协调与调度。相比vue组件,react在较大组件方面的性能更高。如果要手写一个简易版本的React,其核心要实现以下功能,createElement(用于创建元素)、createDOM/updateDOM(用于创建和更新DOM)、render/workLoop(用于生成Fiber和协调运算)、commitWork(用于提交)等,如果还有支持Hooks,还得封闭Hooks相关的方法。

思路

  • 下载react官网仓库中的代码,搞清楚目录结构、各个包的作用。

  • 下载地址:https://github.com/facebook/react,进一步查看packages目录。

  • react-dom 这是DOM渲染的若干功能。

  • react 这是React核心语法及其API封装的包

  • react-reconciler 用于生成“Fiber树”和“协调运算”的。

  • scheduler,它是模拟requestIdleCallback(fn)的兼容性实现,用于执行复杂的任务,当浏览器主线程有“空闲”时执行这些复杂的任务,不霸占浏览器主线程。

  • 用工程化环境或者HTML页面,引入react.js和react.dom.js,在源码中进行调试学习。

  • 如果采用HTML页面的方式来分析React源码,还要引入babel.js,对JSX语法进行编译,在script标签还要添加 type=‘text/babel’。

  • 慢慢通过删减、调试的方式,把react.js中无用的逻辑都删除,得到一个mini-react。

我们需要什么

实现一个简易react

需要用到babel.min.js
react.development.js
react-dom.development.js

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>React</title>
</head>
<body>

  <div id="app"></div><hr>

  <div id='root'></div>

  <script src='./dist/babel.min.js'></script>
  <script src='./dist/react.development.js'></script>
  <script src='./dist/react-dom.development.js'></script>

  <script type='text/javascript'>
    // 创建了一个React元素
    const app = React.createElement('h1', {
     title:'testReact'}, 'Hello React')
    ReactDOM.render(app, document.getElementById('app'))
  </script>

  <script type='text/babel'>
    const App = () => {
     
      const [num, setNum] = React.useState(0)
      return (
        <div>
          <h1>{
      num }</h1>
          <button onClick={
     ()=>setNum(num-1)}>自减</button>
          <button onClick={
     ()=>setNum(num+1)}>自增</button>
        </div>
      )
    }
    ReactDOM.render(<App />, document.getElementById('root'))
  </script>

</body>
</html>

首先实现基本的render和react-dom


// return Fiber基础单元 = { type, props: { children } }
// type 表示当前节点的HTML元素名,也有可能是'TEXT-ELEMENT'
// props 表示当前节点的jsx属性,还包括一个特殊属性children
function createElement(type, props, ...children) {
   
  // 返回一个Fiber单元
  return {
   
    type,
    props: {
   
      ...props,
      children: children.map(ele=>(typeof ele==='object') ? ele : createTextElement(ele))
    }
  }
}

// 文本Fiber
function createTextElement(text) {
   
  return {
   
    type: 'TEXT_ELEMENT',
    props: {
   
      nodeValue: text,
      children: []
    }
  }
}


function isProperty (key) {
   
  return key !== 'children'
}

function render (element, container) {
   
  const dom =
    element.type === 'TEXT_ELEMENT'
      ? document.createTextNode(element.props
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用html-to-react可以将HTML代码转换为React组件。下面是一个示例代码,展示如何使用html-to-react将HTML字符串转换为React组件: ```javascript import React from 'react'; import ReactDOMServer from 'react-dom/server'; import HtmlToReact from 'html-to-react'; class MyComponent extends React.Component { render() { return ( <div>{this.props.children}</div> ); } } const htmlInput = '<div><h1>Title</h1><p>Some text</p></div>'; const processNodeDefinitions = new HtmlToReact.ProcessNodeDefinitions(React); const processingInstructions = [ { // Custom <div> processing shouldProcessNode: function(node) { return node.name === 'div'; }, processNode: function(node, children) { return React.createElement(MyComponent, {}, children); } }, { // Default processing shouldProcessNode: function(node) { return true; }, processNode: processNodeDefinitions.processDefaultNode, }, ]; const reactElement = HtmlToReact.htmlToReactParser.parseWithInstructions(htmlInput, () => true, processingInstructions); const reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement); console.log(reactHtml); ``` 在上面的示例中,我们首先定义了一个React组件`MyComponent`,它包含一个`<div>`元素来显示子元素。然后,我们定义了一个HTML字符串`htmlInput`,它包含一个`<div>`元素和一些子元素。接下来,我们使用`html-to-react`库中的`htmlToReactParser`函数将HTML字符串转换为React组件。我们还定义了一个`processingInstructions`数组,其中包含两个对象,一个用于处理`<div>`元素,另一个用于处理默认情况。最后,我们使用`ReactDOMServer`中的`renderToStaticMarkup`函数将React组件转换为HTML字符串,并将其打印到控制台上。 需要注意的是,`html-to-react`库提供了许多其他处理HTML节点的函数和选项,可以根据需要进行自定义。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值