首页 > 编程语言 >react源码解析手写ReactDom.js和React

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

时间:2023-08-02 11:37:48浏览次数:35  
标签:node container vnode React item 源码 props const js

前言

大家好 我是歌谣 今天给大家带来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

目录结构

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

实现的功能

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

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
}

运行结果

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

总结

我是歌谣 最好的种树是十年前 其次是现在 多看 多写 多输出 这是源码功能实现的部分代码 后续持续优化

标签:node,container,vnode,React,item,源码,props,const,js
From: https://blog.51cto.com/u_14476028/6935189

相关文章

  • JS是门单线程语言
    多线程语言的好处是,在同一时间让cpu处理多个事情。充分的利用cpu多核多线程的资源优势。程序也会执行的更快!支持多线程的语言有特别多,比如java、python等等,但是也有单线程语言如jsclassRunnableDemoimplementsRunnable{privateThreadt;privatefinalStr......
  • jsp上传文件到服务器指定文件夹问题
    ​ javaweb上传文件上传文件的jsp中的部分上传文件同样可以使用form表单向后端发请求,也可以使用ajax向后端发请求    1.通过form表单向后端发送请求         <formid="postForm"action="${pageContext.request.contextPath}/UploadServlet"method="post"e......
  • NodeJS系列(7)- Ant Design Pro 简介
    AntDesignPro是基于AntDesign和umi的封装的一整套企业级中后台前端/设计解决方案,致力于在设计规范和基础组件的基础上,继续向上构建,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。AntDesign是一套企业级......
  • vite 项目webstorm跳转失效 VSCode、vue 无法对 @ 路径 跳转 ,几乎适用于所有webpack、
    在根目录加一个jsconfig.json文件{"compilerOptions":{"baseUrl":".","paths":{"@/*":["src/*"]},"target":"ES6","allowSyntheticDefaultImports&q......
  • 让nlohmann json支持std::wstring和嵌套结构的序列化与反序列化
    nlohmannjson是一个star很高的C++json解析库。要让nlohmannjson支持某个类型T,只要给这个类型T实现一个偏特化的structadl_serializer<T>即可。adl_serializer是这个库里面针对泛型T预定义的适配器。而嵌套结构,本身就支持的。使用预定义的宏NLOHMANN_DEFINE_TYPE_NON_INTRUSI......
  • 通过Vue + intro.js 实现页面新手引导流程功能
    最近需要增加一个新手页面引导流程的功能,在网上搜罗之后发现了intro.js这个插件1.安装依赖npminstallintro.js--save2.在main.js中引用插件//首页引导插件importintrofrom'intro.js'//introjs库import'intro.js/introjs.css'//introjs默认css样式//introjs还......
  • PHPJSON数据格式常见应用及实例解析
    PHPJSON数据格式常见应用及实例解析随着Web应用的兴起和普及,数据的传输和处理已经成为Web开发中不可或缺的一部分。PHP作为一种广泛使用的服务器端编程语言,对于数据的处理和传输也有着非常丰富的支持。其中,JSON数据格式已经成为Web开发中最常用的数据格式之一。本文将结合实例,介......
  • requests--post中json中文编码问题
    问题requestspost提交json数据时,默认在库中ensure_ascii为True。会对中文进行unicode编码。但是有的时候服务端并没有处理中文,没有进行解码,而我们又改不了服务端,就会出现问题!解决修改库的代码,添加上对应的ensure_ascii参数。不推荐,换个环境就用不了了。推荐:自己......
  • react中简单使用echarts图表
    1:下载echarts-for-react插件2:组件内引入importReactEchatrsfrom'echarts-for-react'复制echarts官网图表的option例如:柱形图的option react组件内定义函数存放复制的option并返回importReactfrom'react';importReactEchatrsfrom'echarts-for-react'impor......
  • js sum 函数
    实现:Array.prototype.Sum=function(fn){returneval(this.map(x=>Number(typeoffn=="function"?fn(x):x)).join("+"))||0}用法示例:vararr1=[{name:'xx',value:1},{name:'xx',value:2},{name:'xx'......