Vue自定义渲染器本质是解耦渲染逻辑与目标平台,通过createRenderer传入rendererOptions(含createElement、insert、patchProp等平台接口),将VNode映射到任意环境,复用Vue核心机制而不依赖DOM。

Vue 的自定义渲染引擎本质是解耦渲染逻辑与目标平台,让 Vue 的核心(响应式系统、组件模型、编译器)不再绑定 DOM,而是通过一套可替换的平台抽象接口,把虚拟节点(VNode)映射到任意环境。
它不是重写 Vue,而是“换掉底层驱动”——保留声明式模板和响应式更新机制,只替换 createElement、insert、patchProp 这些与具体平台打交道的操作。
自定义渲染器依赖的核心基础:虚拟 DOM 抽象
Vue 3 的 VNode 是纯 JavaScript 对象,描述 UI 结构但不包含任何平台细节。例如:
{
type: 'div',
props: { id: 'app', class: 'container' },
children: [
{ type: 'span', children: 'Hello' }
]
}这个结构本身不关心是画在浏览器里、Canvas 上、终端里,还是发给 WebGL 渲染管线。它只是数据。真正决定“怎么画”的,是开发者提供的 rendererOptions。
立即学习“前端免费学习笔记(深入)”;
关键入口:createRenderer 函数
Vue 通过 @vue/runtime-core 暴露 createRenderer(options),传入一个配置对象,返回带 render 和 createApp 方法的渲染器实例:
import { createRenderer } from '@vue/runtime-core'
const renderer = createRenderer({
createElement(type) { /* 返回该平台的“元素” */ },
insert(child, parent, anchor) { /* 插入逻辑 */ },
patchProp(el, key, prev, next) { /* 更新属性,如 style/class/事件 */ },
remove(el) { /* 卸载逻辑 */ },
setElementText(el, text) { /* 设置文本内容 */ },
// 还有 createText、createComment、parentNode、nextSibling 等
})这些方法共同构成一个平台适配层。只要实现它们,Vue 就能在这个平台上完成挂载、更新、卸载全流程。
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
渲染流程如何被接管?
当调用 renderer.render(vnode, container) 时:
- Vue 不再调用
document.createElement,而是调用你写的createElement('div') - 不再用
el.appendChild(),而是执行你定义的insert(child, parent) - 属性更新(比如
v-model或:class)触发的是你的patchProp(el, 'class', old, new) - 文本变化走的是
setElementText(el, 'new text') - 组件卸载时,
remove(el)由你控制资源释放(比如 Canvas 清除绘图上下文、WebGL 删除 buffer)
整个过程完全绕开浏览器 DOM API,也无需修改 Vue 源码。
它为什么能跨平台?
因为 Vue 的核心逻辑(diff 算法、响应式追踪、组件生命周期、指令解析、插槽分发)全部运行在 JavaScript 层,只依赖 VNode 树和 rendererOptions 提供的原子操作。只要这些操作能对应到目标平台的能力,就能工作。
常见落地场景包括:
-
Canvas / WebGL:
createElement返回图形对象,patchProp更新顶点或材质参数 -
命令行终端:
setElementText输出 ANSI 字符,insert拼接字符串树 - 小程序 / 原生应用:对接微信/支付宝/React Native 的视图创建 API
- 嵌入式 UI / IoT 屏幕:映射到轻量级图形库或硬件帧缓冲区
所有场景共享同一套 Vue 组件语法和开发体验,只是“输出端”换了。
注意事项:不是所有功能开箱即用
- 指令(如
v-html、v-model)需配合平台语义重新实现 - 事件系统(如
@click)要桥接到目标平台的交互机制(比如 Canvas 的鼠标坐标判断) -
<Teleport>需要querySelector替代方案(如自定义查找容器) - SSR 或 hydrate 场景需额外提供服务端渲染支持函数
这些扩展能力都基于 rendererOptions 的可扩展字段(如 resolveElement、cloneNode),而非硬编码逻辑。
不复杂但容易忽略。

















