js实现vdom
实现虚拟DOM(Virtual DOM)的基本原理
虚拟DOM是一种用JavaScript对象模拟真实DOM树的技术,通过比较新旧虚拟DOM的差异来最小化真实DOM的操作。以下是实现核心功能的步骤:
创建虚拟DOM节点
虚拟DOM节点通常是一个JavaScript对象,包含标签名、属性、子节点等信息:
function createElement(type, props, ...children) {
return {
type,
props: {
...props,
children: children.map(child =>
typeof child === 'object' ? child : createTextElement(child)
)
}
}
}
function createTextElement(text) {
return {
type: 'TEXT_ELEMENT',
props: {
nodeValue: text,
children: []
}
}
}
渲染虚拟DOM到真实DOM
将虚拟节点转换为真实DOM节点并挂载到容器中:
function render(element, container) {
const dom =
element.type === 'TEXT_ELEMENT'
? document.createTextNode('')
: document.createElement(element.type)
Object.keys(element.props)
.filter(key => key !== 'children')
.forEach(name => {
dom[name] = element.props[name]
})
element.props.children.forEach(child =>
render(child, dom)
)
container.appendChild(dom)
}
实现Diff算法
比较新旧虚拟DOM树的差异,只更新变化的部分:
function diff(oldNode, newNode) {
if (!oldNode) return { type: 'CREATE', newNode }
if (!newNode) return { type: 'REMOVE' }
if (changed(oldNode, newNode)) return { type: 'REPLACE', newNode }
if (oldNode.type !== newNode.type) return { type: 'UPDATE', props: diffProps(oldNode, newNode) }
return {
type: 'UPDATE_CHILDREN',
patches: diffChildren(oldNode, newNode)
}
}
function changed(node1, node2) {
return (
typeof node1 !== typeof node2 ||
(typeof node1 === 'string' && node1 !== node2) ||
node1.type !== node2.type
)
}
应用差异更新
根据Diff结果执行最小化DOM操作:

function applyPatch(parent, patch) {
switch (patch.type) {
case 'CREATE':
parent.appendChild(render(patch.newNode))
break
case 'REMOVE':
parent.removeChild(parent.childNodes[patch.index])
break
case 'REPLACE':
parent.replaceChild(render(patch.newNode), parent.childNodes[patch.index])
break
case 'UPDATE':
updateProps(parent.childNodes[patch.index], patch.props)
break
case 'UPDATE_CHILDREN':
patch.patches.forEach((childPatch, index) => {
applyPatch(parent.childNodes[patch.index], childPatch)
})
break
}
}
性能优化建议
- 批量更新:收集多个变更后一次性更新DOM
- Key属性:为列表项添加唯一key以提高Diff效率
- 异步渲染:使用
requestIdleCallback分片处理大型DOM更新
let nextUnitOfWork = null
function workLoop(deadline) {
while (nextUnitOfWork && deadline.timeRemaining() > 1) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
}
requestIdleCallback(workLoop)
}
requestIdleCallback(workLoop)
以上实现展示了虚拟DOM的核心概念,实际项目中可以考虑使用更成熟的库如React的Reconciliation算法或Snabbdom等高效实现。






