VNode 是描述 DOM 节点的 JS 对象,含 tag、props、children 字段,支持原生标签与组件构造函数;render 函数递归将其转为真实 DOM,组件通过 render 方法返回 VNode 实现嵌套与 props 传递。

用 VNode 实现一个极简组件化框架,核心在于:把模板编译成 JavaScript 对象(VNode),再递归挂载到真实 DOM 上。不需要解析 HTML 或实现响应式系统,只聚焦“如何把 VNode 渲染为 DOM”和“如何支持组件嵌套与 props 传递”。
什么是 VNode?它长什么样?
VNode(Virtual Node)是一个描述 DOM 节点的普通 JS 对象,包含标签名、属性、子节点等信息。例如:
{ tag: 'div', props: { id: 'app' }, children: [
{ tag: 'h1', children: ['Hello'] },
{ tag: 'MyButton', props: { label: 'Click me' } }
]}
注意:MyButton 不是字符串而是组件构造函数或对象,这是组件化的关键——VNode 要能表达“这是一个组件实例”,而不仅是原生标签。
手写 render 函数:把 VNode 变成真实 DOM
render 函数接收 VNode,返回 HTMLElement。需处理三类节点:
立即学习“前端免费学习笔记(深入)”;
-
字符串节点 → 创建文本节点
document.createTextNode() -
原生标签节点 →
document.createElement(tag),设置 props(如 class、style、事件),递归挂载 children -
组件节点 → 调用组件的
render()方法得到子 VNode,再递归 render
示例简化版 render:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
function render(vnode, container) {
if (typeof vnode === 'string') {
return document.createTextNode(vnode)
}
const el = document.createElement(vnode.tag)
if (vnode.props) {
Object.keys(vnode.props).forEach(key => {
if (key.startsWith('on')) {
el.addEventListener(key.slice(2).toLowerCase(), vnode.props[key])
} else {
el.setAttribute(key, vnode.props[key])
}
})
}
if (vnode.children) {
vnode.children.forEach(child => {
el.appendChild(render(child, null))
})
}
if (container) container.appendChild(el)
return el
}
定义组件:让 VNode 能引用它
组件是一个带 render() 方法的对象(或函数)。例如:
const MyButton = {
render() {
return {
tag: 'button',
props: { class: 'btn' },
children: [this.props.label || 'default']
}
}
}
在父组件 VNode 中直接写 { tag: MyButton, props: { label: 'OK' } }。render 函数检测到 vnode.tag 是函数/对象时,就创建组件实例(简单起见可直接 new 或 call),再调用其 render 得到子 VNode。
关键点:
- 组件实例需要持有
props,所以 render 前要先做const instance = { props: vnode.props } - 组件的
render()是纯函数,返回 VNode,不操作 DOM - 组件可嵌套:子组件返回的 VNode 同样支持 tag 是组件,形成递归渲染链
挂载与更新:最小闭环
写一个 mount(Component, root) 函数:
- 调用
Component.render()得到根 VNode - 用上面的
render()把它转成 DOM 并 append 到 root
更新暂不实现 diff,直接 unmount + remount(适合学习理解流程)。卸载只需清空容器 innerHTML;进阶可给每个 VNode 记录 el,递归移除事件监听器。
这样你就有了一个可运行的迷你框架:写组件、写 render、生成 VNode、递归挂载——Vue 的核心脉络已清晰可见。

















