哈喽大家好,我是西瓜,本人正在研究vue3的源码,在这里和大家分享一下。
前言
大家用vue3的时候有没有觉得相比js实在是太方便了,那么vue中的模板是怎么渲染下来的呢。
目标
深入理解vue渲染器的挂载流程
流程解读
vue是通过一个函数进行的渲染dom操作
这里给大家举个例子
function render (html, container) {
document.querySelector(container).innerHTML = html
}
当然了,vue可不是只用这么简单就实现了渲染。
vue中render实际是调用一个名为patch的函数进行数据处理,下面我们来实现一下patch
function render (vnode, container) {
patch(null, vnode, container)
}
patch会接收三个参数,
- n1 -> 之前的数据
- n2 -> 新的数据
- container -> 父级元素
patch判断n2是组件类型还是元素类型,如果为元素类型则执行processElement,如果为组件类型会执行processComponent函数。
function patch (n1, n2, container) {
if (typeof n2.type === 'string') {
processElement(n1, n2, container)
} else {
processComponent(n1, n2, container)
}
}
我们先来实现一下vue挂载元素的流程
这里当n1为空时则表示是挂载操作,当n1存在为更新操作,更新操作相对复杂,后面单独出一篇文章讲解更新操作。
当n1不存在执行mountElement,也就是挂载操作
function processElement (n1, n2, container) {
if (!n1) {
mountElement(n2, container)
}
}
mountElement是用来处理挂载数据的,这里我们来实现一下
function mountElement (vnode, container) {
const { type, props, children } = vnode
// type -> 元素类型 div/span等
// props -> 元素的属性
// children -> 子级元素
const el = document.createElement(type)
if (props) {
// 因为在vue中我们会把开头为on的数据认为事件,所以只需要判断on来区分事件
for (const key in props) {
const val = props[key]
if (/^on/.test(key)) {
// 绑定事件
const _event = key.slice(2).toLocaleLowerCase()
el.addEventListener(_event, val)
} else {
// 如果属性没有则删除属性,如果有就进行添加操作
if (val === null || val === undefined) {
el.removeAttribute(key)
} else {
el.setAttribute(key, val)
}
}
}
}
// 如果子级为多个的就遍历执行patch,否则就赋值
if (Array.isArray(children)) {
children.forEach((childNode) => {
patch(null, childNode, el)
})
} else {
el.textContent = children
}
// 添加到父级中
container.append(el)
}
这样我们就实现了一个vue挂载元素的简单流程。
大家也可以查看我的github地址,github.com/Rafael-wxd
实现了一个简单的vue3
觉得可以的就欢迎点赞、收藏加关注吧。