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

相关推荐
dy17171 小时前
element-plus表格默认展开有子的数据
前端·javascript·vue.js
2501_915918414 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
程序员的世界你不懂5 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
索迪迈科技5 小时前
网络请求库——Axios库深度解析
前端·网络·vue.js·北京百思可瑞教育·百思可瑞教育
gnip5 小时前
JavaScript二叉树相关概念
前端
attitude.x6 小时前
PyTorch 动态图的灵活性与实用技巧
前端·人工智能·深度学习
β添砖java6 小时前
CSS3核心技术
前端·css·css3
空山新雨(大队长)6 小时前
HTML第八课:HTML4和HTML5的区别
前端·html·html5
猫头虎-前端技术7 小时前
浏览器兼容性问题全解:CSS 前缀、Grid/Flex 布局兼容方案与跨浏览器调试技巧
前端·css·node.js·bootstrap·ecmascript·css3·媒体