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

前言

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

创建项目

首先npx create-react-app xxx

降为17

bash "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

目录结构

在这里插入图片描述

实现的功能

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

```bash let jsx = (

我是歌谣
)

ReactDOM.render(jsx, document.getElementById('root')); ```

局部实现代码

```bash 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) }

```

数组遍历的实现

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

})

```

方法监听的实现

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

核心代码

主入口 index.js

```bash /** @jsxRuntime classic */ import ReactDOM from './kreact/ReactDom'; import React from "./kreact" import './index.css'; function FuncGeyao(props) { return

name:{props.name}
} class ClassGeyao extends React.Component { handle=()=>{ console.log("geyaoisnice") } render() { return
我是芳芳
{[0,1,2].map(item=>{
  return <FuncGeyao key={item} name={"geyao"+item}></FuncGeyao>
})}

</div>

} } let jsx = (

我是歌谣
)

ReactDOM.render(jsx, document.getElementById('root'));

```

index.js(React)

```bash 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

```bash 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 } ```

运行结果

在这里插入图片描述

总结

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

posted @ 2023-08-02 10:54  前端导师歌谣  阅读(30)  评论(0)    收藏  举报  来源