手把手实现一个简易版React:理解虚拟DOM
James Park | 2026-08-09T09:42:00 | JavaScript, Frontend
用200行代码实现一个简易版React,深入理解虚拟DOM、diff算法和patch过程
# 手把手实现一个简易版React:理解虚拟DOM 面试被问"虚拟DOM的原理",光说概念总觉得不踏实。干脆自己实现一个迷你版。 ## createElement ```javascript // 创建虚拟DOM节点 function createElement(type, props) { var children = Array.prototype.slice.call(arguments, 2); return { type: type, props: props || {}, children: children.flat().map(function(child) { return typeof child === 'object' ? child : createTextNode(child); }) }; } function createTextNode(text) { return { type: 'TEXT', props: { nodeValue: text }, children: [] }; } ``` ## render - 虚拟DOM变真实DOM ```javascript function render(vnode, container) { var dom; if (vnode.type === 'TEXT') { dom = document.createTextNode(vnode.props.nodeValue); } else { dom = document.createElement(vnode.type); // 设置属性 Object.keys(vnode.props).forEach(function(key) { if (key.startsWith('on')) { var eventName = key.slice(2).toLowerCase(); dom.addEventListener(eventName, vnode.props[key]); } else { dom.setAttribute(key, vnode.props[key]); } }); } // 递归渲染子节点 vnode.children.forEach(function(child) { render(child, dom); }); container.appendChild(dom); } ``` ## 简易diff ```javascript function diff(oldVNode, newVNode) { // 类型不同直接替换 if (oldVNode.type !== newVNode.type) { return { type: 'REPLACE', newVNode: newVNode }; } // 文本节点比较内容 if (oldVNode.type === 'TEXT') { if (oldVNode.props.nodeValue !== newVNode.props.nodeValue) { return { type: 'TEXT', text: newVNode.props.nodeValue }; } } // 同类型节点比较props和children return { type: 'UPDATE', props: diffProps(oldVNode, newVNode) }; } ``` 理解了这三步——**创建虚拟节点、渲染成真实DOM、diff比较差异**——就掌握了React的核心思想。