react源码解析手写ReactDom.js和React

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: react源码解析手写ReactDom.js和React

前言

大家好 我是歌谣 今天给大家带来react源码部分的实现


创建项目

首先npx create-react-app xxx


降为17

"dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },

环境

React 17.0.2


目录结构

image.png


实现的功能

原生标签和类组件和函数组件的渲染

let jsx = (
  <div>
    <div className='geyao'>我是歌谣</div>
    <FuncGeyao name="geyao"></FuncGeyao>
    <ClassGeyao name="geyao"></ClassGeyao>
  </div>
)
ReactDOM.render(jsx, document.getElementById('root'));

局部实现代码

function mount(vnode, container) {
    const { vtype } = vnode
    if (!vtype) {
        mountTextNode(vnode, container) //处理文本节点
    }
    if (vtype == 1) {
        mountHtml(vnode, container) //处理原生标签
    }
    if(vtype===3){ //处理函数组件
        mountFunc(vnode, container)
    }
    if(vtype===2){ //处理类组件
        mountClass(vnode, container)
    }
}
function mountTextNode(vnode, container) {
    const node = document.createTextNode(vnode)
    container.appendChild(node)
}
function mountHtml(vnode, container) {
    const { type, props } = vnode
    var node = document.createElement(type)
    const { children,...rest } = props
    children.map(item => {
        if(Array.isArray(item)){
            item.map(c=>{
                mount(c,node)
            })
        }else{
            mount(item, node)
        }
        // mount(item, node)
    })
    Object.keys(rest).map(item=>{
        if(item==='className'){
            node.setAttribute("class",rest[item])
        }
        if(item.slice(0,2)==="on"){
            node.addEventListener("click",rest[item])
        }
    })
    container.appendChild(node)
}
function mountFunc(vnode, container){
    const {type,props}=vnode
    const node=type(props)
    mount(node,container)
}
function mountClass(vnode, container){
    const {type,props}=vnode
   const cmp=new type(props)
   const node=cmp.render()
    mount(node,container)
}

数组遍历的实现

Object.keys(rest).map(item=>{
        if(item==='className'){
            node.setAttribute("class",rest[item])
        }
    })

方法监听的实现

Object.keys(rest).map(item=>{
        if(item.slice(0,2)==="on"){
            node.addEventListener("click",rest[item])
        }
    })



核心代码

主入口 index.js

/** @jsxRuntime classic */
import ReactDOM from './kreact/ReactDom';
import React from "./kreact"
import './index.css';
function FuncGeyao(props) {
  return <div className='geyao'>
    name:{props.name}
  </div>
}
class ClassGeyao extends React.Component {
  handle=()=>{
    console.log("geyaoisnice")
  }
  render() {
    return <div onClick={this.handle} className='geyao'>我是芳芳
    {[0,1,2].map(item=>{
      return <FuncGeyao key={item} name={"geyao"+item}></FuncGeyao>
    })}
    </div>
  }
}
let jsx = (
  <div>
    <div className='geyao'>我是歌谣</div>
    <FuncGeyao name="geyao"></FuncGeyao>
    <ClassGeyao name="geyao"></ClassGeyao>
  </div>
)
ReactDOM.render(jsx, document.getElementById('root'));

index.js(React)

function createElement(type,props,...children){
    console.log(arguments,"createElement")
    console.log(type,props,children,"children")
    props.children=children;
    let vtype;
    if(typeof type==="string"){
        vtype=1;
    }
    if(typeof type==="function"){
        vtype=type.isReactComponent?2:3
    }
    return {
        vtype,
        type,
        props
    }
}
 class Component{
    static isReactComponent={}
    constructor(props){
        this.props=props
    }
}
export default{
    Component,
    createElement
}

ReactDom.js

function render(vnode, container) {
    console.log("enter", vnode)
    mount(vnode, container)
}
function mount(vnode, container) {
    const { vtype } = vnode
    if (!vtype) {
        mountTextNode(vnode, container) //处理文本节点
    }
    if (vtype == 1) {
        mountHtml(vnode, container) //处理原生标签
    }
    if(vtype===3){ //处理函数组件
        mountFunc(vnode, container)
    }
    if(vtype===2){ //处理类组件
        mountClass(vnode, container)
    }
}
function mountTextNode(vnode, container) {
    const node = document.createTextNode(vnode)
    container.appendChild(node)
}
function mountHtml(vnode, container) {
    const { type, props } = vnode
    var node = document.createElement(type)
    const { children,...rest } = props
    children.map(item => {
        if(Array.isArray(item)){
            item.map(c=>{
                mount(c,node)
            })
        }else{
            mount(item, node)
        }
        // mount(item, node)
    })
    Object.keys(rest).map(item=>{
        if(item==='className'){
            node.setAttribute("class",rest[item])
        }
        if(item.slice(0,2)==="on"){
            node.addEventListener("click",rest[item])
        }
    })
    container.appendChild(node)
}
function mountFunc(vnode, container){
    const {type,props}=vnode
    const node=type(props)
    mount(node,container)
}
function mountClass(vnode, container){
    const {type,props}=vnode
   const cmp=new type(props)
   const node=cmp.render()
    mount(node,container)
}
export default {
    render
}

运行结果


image.png

相关文章
|
1月前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
71 17
|
4天前
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
57 33
|
25天前
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
103 24
|
28天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
28天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
28天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
4天前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
16 0
|
1月前
|
Web App开发 移动开发 HTML5
html5 + Three.js 3D风雪封印在棱镜中的梅花鹿动效源码
html5 + Three.js 3D风雪封印在棱镜中的梅花鹿动效源码。画面中心是悬浮于空的梅花鹿,其四周由白色线段组成了一个6边形将中心的梅花鹿包裹其中。四周漂浮的白雪随着多边形的转动而同步旋转。建议使用支持HTML5与css3效果较好的火狐(Firefox)或谷歌(Chrome)等浏览器预览本源码。
92 2
|
29天前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
2月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
41 1
JavaScript中的原型 保姆级文章一文搞懂

推荐镜像

更多