JSX底层渲染机制

JSX底层渲染机制

一,.步骤

1.把我们写的jsx语法编译为虚拟DOM【virtualDOM】

虚拟DOM对象:框架自己内部构建的一套对象体系(对象的相关成员都是React内部绑定的),基于这些属性描述出我们所构建视图中的DOM接的相关特征

@1基于babel-preset-react-app 把jsx编译为React.createElement(...)的格式。

只要是元素节点,必然会基于createElement进行处理!

React.createElement(ele,props,...children)

+ele: 元素标签名【或组件】

+props: 元素的属性集合(对象),如果没有任何的属性,则此值为null

+children: 第三个及其以后得参数,都是当前元素的子节点

如下图jsx

javascript 复制代码
root.render{
	<>
		<h2 className='title' style={styleObj}>XXXX</h2>
		<div className='box'>
			<span>x</span>
			<span>y</span>
		</div>
	</>
}

编译为

@再把CreateElement的方法执行,创建出VirtualDom对象【也有称为:JSX元素、JSX对象、ReactChild对象...】

javascript 复制代码
//虚拟DOM对象
virtualDOM={
	$$typeOf:Symbol(react.element),
	ref:null,
	key:null,
	type:标签名【或组件】,
	//存储了元素相关属性&子节点信息
	props:{
		元素的相关节点
		children:子节点信息【没有子节点就没有则个属性、属性可能是一个值,也可能是一个数组】
	}
}
javascript 复制代码
/*createElement:创建虚拟DOM对象*/
export fucnction createElement(ele,props,...children){
	let virtualDOM={
		$$typeOf:Symbol('react.element'),
		key:null,
		key:null,
		ref:null,
		type:null. 
		props:{}
	};
	let len=children,length
	virtualDOM.type=ele;
	if(props){
		virtualDOM.props={...props}
	}
	if(len===1){
		virtualDOM.props.children=children[0]
	}else if(len>1){
		virtualDOM.props.children=children
	}
	return virtualDOM
}

2.构建的virtualDOM渲染为真实的DOM元素

真实DOM:浏览器页面中,最后渲染出来,让用户看见的DOM元素

基于ReactDOM中的render方法处理
v16

javascript 复制代码
ReactDOM.render(
	<>...</>
	domcument.getElementById('root')
)

v18

javascript 复制代码
const root = React.createRoot(dociment.getElementById('root'))
root,render(
	<>...</>
)

补充:第一次渲染页面是直接从虚拟DOM ---> 真实ODM,但是后续视图更新的时候会经过一个DOM-DIFF的对比,计算出补丁包PATCH(两次视图差异部分),把PATCH补丁包进行渲染

javascript 复制代码
/*render:把虚拟DOM变为真实DOM*/
export function render(virtualDOM,container){
	let {type,props}=virtualDOM;
	if(typeof type==='string'){
		//存储的是标签名:动态创建这样一个标签
		let ele=domcument.createElement(type);
		//为标签设置相关属性&节点
		each(props,(value,key)=>{
			//classNmae的处理
			if(key==='className'){
				ele.className=value
				return
			}
			//style的处理:value存储的是样式对象
			if(key==='style'){
				each(value,(val,attr)=>{
					ele.style[attr]=val
				})
				return
			}
			//子节点的处理:value存储的children属性值
			if(key==='children'){
				let children = value
				if(children.length===1){
					children=[children]
				}
				children.forEach(child=>{
					//子节点是文本节点:直接插入
					if(typeof child==='string'){
						ele.appendChild(domcument.createTextNode(child))
						return;	
					}
					//子节点又是一个虚拟ODM:递归处理
					render(child,ele)
				})
				return
			}
			ele.setAttribute(key,value);
		})
		container.appendChild(ele)
	}
}
相关推荐
IT_陈寒7 分钟前
Python的线程池把我CPU跑满了,原来少传了个参数
前端·人工智能·后端
喜欢的名字被抢了16 分钟前
写-Chrome-扩展时踩过的那些-MV3-的坑
前端·chrome
网安老伯26 分钟前
网络安全基础要点知识介绍(非常详细),零基础入门到精通,看这一篇就够了
运维·前端·网络协议·web安全·网络安全·职场和发展
wuqingshun31415931 分钟前
springBoot是如何通过main方法启动web项目的?
前端·spring boot·后端
xxwl58531 分钟前
HTML 小总结:从骨架到枝叶,系统掌握网页结构
前端·html
●VON33 分钟前
鸿蒙 PC Markdown 编辑器 Bridge 协议:原生外壳与 Web 内核的状态同步
前端·华为·编辑器·harmonyos·鸿蒙
MrDJun1 小时前
分享一款免费实用的网页变动监控工具:PageWatch.tech
前端·javascript·vue.js
米码收割机1 小时前
【web】邻里悦站—社区便民服务平【独一无二】(源码+说明文档)
前端
程序员爱钓鱼1 小时前
Rust Option 详解:安全处理“可能存在,也可能不存在”的值
前端·后端·rust
程序员爱钓鱼1 小时前
Go Modules 包管理详解:go.mod、go.sum 与依赖管理
前端·后端·go