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 @   前端导师歌谣  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示