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

相关推荐
blackorbird1 小时前
Edge 浏览器 IE 模式成攻击突破口:黑客借仿冒网站诱导攻击
前端·edge
谷歌开发者2 小时前
Web 开发指向标 | Chrome 开发者工具学习资源 (一)
前端·chrome·学习
名字越长技术越强2 小时前
Chrome和IE获取本机ip地址
前端
天***88962 小时前
Chrome 安装失败且提示“无可用的更新” 或 “与服务器的连接意外终止”,Chrome 离线版下载安装教程
前端·chrome
半梦半醒*2 小时前
zabbix安装
linux·运维·前端·网络·zabbix
清羽_ls3 小时前
React Hooks 核心规则&自定义 Hooks
前端·react.js·hooks
你的人类朋友3 小时前
“签名”这个概念是非对称加密独有的吗?
前端·后端·安全
西陵3 小时前
Nx带来极致的前端开发体验——任务缓存
前端·javascript·架构
10年前端老司机4 小时前
Promise 常见面试题(持续更新中)
前端·javascript
潘小安4 小时前
跟着 AI 学 (一)- shell 脚本
前端·ci/cd·vibecoding