实现一个mini-react

首先 说下原理

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>Reacttitle>
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

你可能感兴趣的:(react.js,javascript,前端)