这篇文章上次修改于 2026 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
什么是Virtual DOM?
所谓virtual,指的是对真实DOM的一种模拟。相对于直接操作真实的DOM结构,我们构建一棵虚拟的树,将各种数据和操作直接应用在这棵虚拟的树上,然后再将对虚拟的树的修改应用到真实的DOM结构上。
这样有以下好处:
- 可能会减少DOM操作次数,带来性能上的提升,即使我们频繁操作虚拟DOM,我们只需要一定时刻一次性同步修改到真实DOM上即可
- 真实的HTML节点有两百多个属性和方法,使用虚拟节点,能在数据结构上节省内存。
- 虚拟DOM不依赖浏览器环境,能在node环境实现,可以使用虚拟DOM生成html字符串,实现SSR
使用新的数据结构表示HTML节点
尝试在控制台打印一个HTML节点的所有属性和方法,我们会发现HTML节点是一个非常巨大的数据结构。
HTMLElement由两百多个属性和方法
而90%以上的属性和方法我们并不关心。
对Element节点的表示
所以我们可以尝试用下面的结构表示Element节点。
export default class VNode {
constructor(tagName, attrs, children) {
this.tagName = tagName
this.attributes = attrs
this.children = children
}
}
那么对于:
<div class='container'></div>
我们就能用VNode('div', {class: 'container'}, [])
来表示了。
然后我们为VNode添加render方法,实现向真实节点的转换。
class VNode {
constructor(tagName, attrs, children) {
this.tagName = tagName
this.attributes = attrs
this.children = children
}
render() {
let element = document.createElement(this.tagName)
Object.keys(this.attributes).forEach(key => {
element.setAttribute(key, this.attributes[key])
})
this.children.forEach(child => {
element.appendChild(child.render())
})
return element
}
}
对于Text节点的表示
对于text节点,暂时只关心文本内容
class TextNode {
constructor(content) {
this.content = content
}
render() {
return document.createTextNode(this.content)
}
}
在对上面两种节点的改造下,我们尝试表示一下html:
image.png
let virtualDom = new VNode('div', {class: 'container'}, [
new TextNode('some content'),
new VNode('span', {}, [
new TextNode('other content')
])
])
本文demo源码: https://github.com/boomler/virtual-dom-demos/tree/master/demo1
作者:浩神
链接:https://www.jianshu.com/p/2d24d8095d1c
来源:简书
没有评论
博主关闭了评论...