前言
大家好 我是歌谣 今天给大家带来react源码部分的实现
环境
React 17.0.2
目录结构
创建项目
首先npx create-react-app xxx
降为17
代码语言:javascript复制"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"
},
实现的功能
原生标签和类组件和函数组件的渲染
代码语言:javascript复制let jsx = (
<div>
<div className='geyao'>我是歌谣</div>
<FuncGeyao name="geyao"></FuncGeyao>
<ClassGeyao name="geyao"></ClassGeyao>
</div>
)
ReactDOM.render(jsx, document.getElementById('root'));
局部实现代码
代码语言:javascript复制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)
}
数组遍历的实现
代码语言:javascript复制Object.keys(rest).map(item=>{
if(item==='className'){
node.setAttribute("class",rest[item])
}
})
方法监听的实现
代码语言:javascript复制 Object.keys(rest).map(item=>{
if(item.slice(0,2)==="on"){
node.addEventListener("click",rest[item])
}
})
核心代码
主入口 index.js
代码语言:javascript复制/** @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)
代码语言:javascript复制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
代码语言:javascript复制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
}
运行结果
总结
我是歌谣 最好的种树是十年前 其次是现在 多看 多写 多输出 这是源码功能实现的部分代码 后续持续优化