记笔记--React源码之路--实现从jsx、函数组件、类组件渲染到浏览器界面
2021/7/14 17:05:46
本文主要是介绍记笔记--React源码之路--实现从jsx、函数组件、类组件渲染到浏览器界面,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
React版本号:17.0.1
目的:实现jsx、函数组件、类组件渲染到浏览器界面:手撸 ReactDOM.render
前提须知:我们需要了解虚拟DOM,React已经与babel合作,我们写的jsx会被babel转义为下图中的一个用于描述JavaScript节点的对象,虚拟DOM就张下图这样哈
界面图:
控制台查看真实DOM布局:
index.js文件代码:
// 模拟render方法文件引用 import TreactDom from './TestDemo/TreactDom' // 模拟类组件继承文件引用 import Treact from './TestDemo/Treact' // 模拟函数组件渲染 function FuncComponent(props) { return ( <div className="func-border"> <p>函数组件--{props.name}</p> </div> ) } // 模拟类组件渲染 class ClassComponent extends Treact.Component { render () { return ( <div className="calss-border"> <p>类组件--{this.props.name}</p> </div> ) } } const JSX = ( <div className="div"> <h1 id="h1">我是h1</h1> <span style={{ color: 'red', background: 'pink' }}>hello</span><br/> 我是纯文本<br/> <FuncComponent name="func" /> <ClassComponent name="class" /> </div> ) TreactDom.render(JSX, document.getElementById('root'))
TreactDom.js文件代码:
function render (vnode, container) { console.log('vnode: ', vnode) // vnode-->node let node = createNode(vnode) // node插入到container中 container.appendChild(node) } // 由虚拟dom生成真实dom的函数 function createNode (vnode) { let {type} = vnode let node = null if (typeof type === 'string') { // 创建标签节点:div、p、a等等 node = updateHostComponent(vnode) } else if (typeof type === 'function') { // 函数、类组件 node = type.prototype.isReactComponet ? updateClassComponent(vnode) : updateFuncComponent(vnode) } else { // 创建文本节点 node = updateTextNode(vnode) } return node } // 类组件 function updateClassComponent(vnode) { let {type, props} = vnode let instance = new type(props) let vvnode = instance.render() let node = createNode(vvnode) return node } // 函数组件 function updateFuncComponent(vnode) { let {type, props} = vnode let vvnode = type(props) let node = createNode(vvnode) return node } // 标签节点 function updateHostComponent(vnode) { let {type, props} = vnode let node = document.createElement(type) updateNodeProps(props, node) reconcileChildren(props.children, node) return node } // 给真实dom上添加属性:style、className、id等等 function updateNodeProps(props, node) { Object.keys(props).filter(key => key != 'children').forEach(key => { if (key == 'style') { let str = Object.keys(props.style).reduce((prev, k) => { prev.push(`${k}: ${props.style[k]}`) return prev }, []).join(';') node.style = str } else { node[key] = props[key] } }) } // 遍历 props.children,利用递归的思路将子虚拟dom节点生成真实dom,并且挂载到真实dom父节点上 function reconcileChildren(children, container) { if (!children) return const newChildren = Array.isArray(children) ? children : [children] for (let i = 0; i < newChildren.length; i++) { const vnode = newChildren[i]; render(vnode, container) } } // 创建文本节点 function updateTextNode(vnode) { return document.createTextNode(vnode) } export default { render }
Treact.js文件代码:
function Component(props) { // 这里需要将props挂载到this上,你的类组件才能使用 this.props 哈 this.props = props } // 表示是类组件:为啥不用 Boolean 值:因为源码是这样标识的,应该是react发展的历史原因吧 Component.prototype.isReactComponet = {} export default { Component }
注:代码逻辑并没有去做校验哈,这里都只是走的理想逻辑
这篇关于记笔记--React源码之路--实现从jsx、函数组件、类组件渲染到浏览器界面的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-21Vue3教程:新手入门到实践应用
- 2024-12-21VueRouter4教程:从入门到实践
- 2024-12-20Vue3项目实战:从入门到上手
- 2024-12-20Vue3项目实战:新手入门教程
- 2024-12-20VueRouter4项目实战:新手入门教程
- 2024-12-20如何实现JDBC和jsp的关系?-icode9专业技术文章分享
- 2024-12-20Vue项目中实现TagsView标签栏导航的简单教程
- 2024-12-20Vue3入门教程:从零开始搭建你的第一个Vue3项目
- 2024-12-20从零开始学习vueRouter4:基础教程
- 2024-12-20Vuex4课程:新手入门到上手实战全攻略