轻松实现MiniVue渲染:核心渲染器攻略
2023-12-22 00:54:43
手写简易的MiniVue(02-渲染器实现)
MiniVue 02 渲染器实现
前言
在上一篇文章中,我们实现了响应式系统。现在,我们将实现渲染器,这是 MiniVue 的核心部分,负责将虚拟节点挂载到真实的 DOM 上,并进行更新。在这一部分,我们将实现三个函数:
h
函数:返回虚拟节点对象mount
函数:用于将虚拟节点挂载到真实的 DOM 上patch
函数:用于更新虚拟节点
1. h
函数
h
函数是创建虚拟节点对象的函数。虚拟节点是 MiniVue 中用来 DOM 元素的轻量级对象,它包含了元素的标签名、属性和子元素。
// h函数的实现
function h(tag, props, children) {
return {
tag,
props,
children
}
}
h
函数的第一个参数是元素的标签名,例如 "div"
、"p"
等。第二个参数是元素的属性,是一个对象,例如 { id: "app" }
。第三个参数是元素的子元素,可以是虚拟节点对象、字符串或数组。
例如,以下代码创建了一个带有 id
属性的 div
元素,并包含两个子元素:一个带有 class
属性的 p
元素和一个文本节点:
const vnode = h("div", { id: "app" }, [
h("p", { class: "text-center" }, "Hello, MiniVue!"),
"World"
])
2. mount
函数
mount
函数用于将虚拟节点挂载到真实的 DOM 上。它首先创建一个真实的 DOM 元素,然后将虚拟节点的属性和子元素附加到这个真实的 DOM 元素上。
// mount函数的实现
function mount(vnode, container) {
// 创建真实的 DOM 元素
const el = createElement(vnode.tag)
// 设置元素属性
for (const key in vnode.props) {
el.setAttribute(key, vnode.props[key])
}
// 递归挂载子元素
vnode.children.forEach(child => {
mount(child, el)
})
// 将元素添加到容器中
container.appendChild(el)
}
mount
函数的第一个参数是虚拟节点对象,第二个参数是将虚拟节点挂载到的容器元素。
mount
函数首先创建一个真实的 DOM 元素,然后将虚拟节点的属性和子元素附加到这个真实的 DOM 元素上。最后,将元素添加到容器中。
3. patch
函数
patch
函数用于更新虚拟节点。当虚拟节点发生变化时,patch
函数会将变化应用到真实的 DOM 上。
// patch函数的实现
function patch(oldVnode, newVnode) {
// 比较标签名
if (oldVnode.tag !== newVnode.tag) {
// 替换元素
const newEl = createElement(newVnode.tag)
oldVnode.el.parentNode.replaceChild(newEl, oldVnode.el)
// 递归更新子元素
newVnode.children.forEach(child => {
mount(child, newEl)
})
} else {
// 更新属性
for (const key in newVnode.props) {
if (newVnode.props[key] !== oldVnode.props[key]) {
oldVnode.el.setAttribute(key, newVnode.props[key])
}
}
// 更新子元素
const oldChildren = oldVnode.children
const newChildren = newVnode.children
// 比较子元素的长度
if (oldChildren.length !== newChildren.length) {
// 更新子元素
updateChildren(oldChildren, newChildren)
} else {
// 递归更新子元素
for (let i = 0; i < oldChildren.length; i++) {
patch(oldChildren[i], newChildren[i])
}
}
}
}
patch
函数的第一个参数是旧的虚拟节点对象,第二个参数是新的虚拟节点对象。
patch
函数首先比较两个虚拟节点的标签名。如果标签名不同,则替换元素。如果标签名相同,则更新属性和子元素。
总结
在本文中,我们实现了 MiniVue 的渲染器,包括 h
函数、mount
函数和 patch
函数。这些函数使我们能够将虚拟节点挂载到真实的 DOM 上,并进行更新。