【vue3 原理】初始化元素流程

前言

初始化组件流程中的最后提到:

因为对根组件拆箱后只是得到了下一个层元素类型的vnode,没有实现对元素类型vnode的渲染逻辑

因此我们来实现这一部分

拆箱

runtime-core/renderer.js

diff 复制代码
function patch(vnode, container){
+	if(typeof vnode.type === 'string') {
+		processElement(vnode, container)
+	} else if(typeof vnode.type === 'object' && vnode.type !== null) {
		processComponent(vnode, container)	
+	}
}

元素类型的vnode的不需要挂载、初始化等一系列操作,和初始化组件流程不同需要走不同的逻辑

处理元素类型

runtime-core/renderer.js

js 复制代码
function processElement(vnode, container) {
	mountElement(vnode, container)
}

和[[初始化组件流程#处理组件|处理组件]]一样有两种情况:

  • 视图初始化
  • 视图更新

先关注初始化

初始化元素

runtime-core/renderer.js

js 复制代码
function mountElement(vnode, container) {
	const el = document.createElement('div')

	el.textContent = 'Hello, World'

	el.setAttribute('id', 'root')

	document.body.append(el)
}

这里虽然写死了渲染逻辑,但原理都是这个原理

创建元素

runtime-core/renderer.js

diff 复制代码
function mountElement(vnode, container) {
+	const el = document.createElement(vnode.type)

	el.textContent = 'Hello, World'

	el.setAttribute('id', 'root')

	document.body.append(el)
}

设置子节点

runtime-core/renderer.js

diff 复制代码
function mountElement(vnode, container) {
	const el = document.createElement(vnode.type)

+	const { children } = vnode
+	if (typeof children === 'string') {
+		el.textContent = children
+	} else if (Array.isArray(children)) {
+		 children.forEach(v => {
+			 patch(v, el)
+		 })
+	}

	el.setAttribute('id', 'root')

	document.body.append(el)
}
  • 子节点为字符串:直接覆盖
  • 子节点为数组:因此数组的成员必须由vnode组成,所以需要遍历递归[[初始化元素流程#拆箱|拆箱]],注意此时容器应该是当前元素

设置属性

runtime-core/renderer.js

diff 复制代码
function mountElement(vnode, container) {
	const el = document.createElement(vnode.type)

	const { children } = vnode
	if (typeof children === 'string') {
		el.textContent = children
	} else if (Array.isArray(children)) {
		 children.forEach(v => {
			 patch(v, el)
		 })
	}

+	const { props } = vnode
+	for(const key in props){
+		el.setAttribute(key, props[key])
+	}

	document.body.append(el)
}

props只能是对象,遍历设值即可

插入元素

runtime-core/renderer.js

diff 复制代码
function mountElement(vnode, container) {
	const el = document.createElement(vnode.type)

	const { children } = vnode
	if (typeof children === 'string') {
		el.textContent = children
	} else if (Array.isArray(children)) {
		 children.forEach(v => {
			 patch(v, el)
		 })
	}

	const { props } = vnode
	for(const key in props){
		el.setAttribute(key, props[key])
	}

+	container.append(el)
}

要注意插入到那个容器元素中

总结

初始化元素的流程和初始化组件流程的不同只是在拆箱时多了一条分支

到这里视图的初始化流程基本上没问题了,后续会慢慢补充一些细节

预告

前面的 demo 中我们打算在根组件render中使用this.msg获取setup状态,显然还没有实现这部分逻辑,看不到效果,只有undefinedthis是什么?它是怎么获取状态的?留到下一节解答

相关推荐
hh随便起个名4 分钟前
React组件通信
前端·react.js·前端框架
前端 贾公子6 分钟前
vite-plugin-eruda-pro 在vite中使用eruda
前端
Jackson__30 分钟前
Agent Skill 和 Rules 有什么区别?
前端·agent·ai编程
不要卷鸿蒙啊34 分钟前
【鸿蒙开发】HMRouter一款和好用的管理路由三方工具
前端·harmonyos
李剑一34 分钟前
数字孪生大屏必看:Cesium 3D 模型选中交互,3 种高亮效果拿来就用!
前端·vue.js·cesium
奶昔不会射手1 小时前
自定义vue3函数式弹窗
前端·javascript·css
new code Boy1 小时前
前端全栈之路
前端
牛奶1 小时前
为什么敲几个字母就能访问网站?DNS原理大揭秘
前端·http·dns
wuhen_n2 小时前
破冰——建立我们的AI开发实验环境
前端·javascript
HelloReader2 小时前
Flutter 自适应布局一套代码适配手机和平板(十二)
前端