【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是什么?它是怎么获取状态的?留到下一节解答

相关推荐
胡萝卜术3 小时前
力扣5. 最长回文子串
前端·javascript·面试
我星期八休息4 小时前
网络编程—应用层HTTP协议
linux·运维·开发语言·前端·网络·网络协议·http
不好听6134 小时前
前端路由完全指南(下篇):懒加载、History 栈与工程化实践
前端·react.js
圣光SG6 小时前
Java Web入门基础知识笔记
java·前端·笔记
cyforkk7 小时前
Vercel 绑定自定义域名极简配置指南
服务器·前端·网络
IT_陈寒8 小时前
React useEffect依赖数组中埋的坑,这次终于让我逮到了
前端·人工智能·后端
FourAu9 小时前
2026 前端突围指南:从 ESR 边缘渲染到封装 Web AI SDK,聊聊 AI 时代的职业进化
前端·人工智能
Zkeq9 小时前
不止是聊天框:我用 EdgeOne Makers Agents 给烹饪 APP 加了一位能“改菜谱”的 AI 主厨
前端
咩咩啃树皮10 小时前
第32篇:前端本地存储全解——Cookie、localStorage、sessionStorage 区别与实战
前端