第 30 题:Vue3 自定义渲染器(Custom Renderer)原理- 为什么 Vue 能渲染到 DOM / Canvas / WebGL / 三方平台

第 29 题:Vue3 自定义渲染器(Custom Renderer)原理 ------ 为什么 Vue 能渲染到 DOM / Canvas / WebGL / 三方平台?

结构同样是你喜欢的:
核心回答 → 深度原理 → 流程图 → 实战代码示例 → 面试官追问 → 高分总结


🎯 一、核心回答(面试官最想听)

Vue3 的渲染系统是基于 "平台无关(Platform-Agnostic)" 设计的。

其本质:

  • 虚拟 DOM(VNode)是平台无关的
  • 平台相关的 DOM API(createElement、patchProp、insert、remove)被抽象成 hostXXX 函数
  • 自定义渲染器通过 createRenderer() 自己提供这些 hostAPI,就能让 Vue 渲染到任何环境。

所以:

Vue3 = 渲染框架(runtime-core) + 平台适配器(runtime-dom)

DOM、Canvas、WebGL、MiniApp 都只是"适配器不同,核心相同"。


🎯 二、深度原理(高端面试官会重点听)


1️⃣ Vue2 为什么不能自定义渲染器?

因为 Vue2 把:

  • VNode 处理
  • DOM 操作

写死在一起。

Vue3 把它们完全拆开:

核心(runtime-core)

  • diff 算法
  • vnode 结构
  • 组件系统
  • 更新队列

平台(runtime-dom)

  • document.createElement
  • el.innerHTML
  • addEventListener

2️⃣ Vue3 自定义渲染器关键 API:createRenderer

源码路径:
packages/runtime-core/src/renderer.ts

核心接口:

lua 复制代码
createRenderer({
  createElement,
  patchProp,
  insert,
  remove,
  setElementText
})

你可以把它想象成:

Vue3 把 DOM 操作外包给你了。

你提供函数,Vue 负责调用。


3️⃣ Vue 渲染流程(可视化理解)

scss 复制代码
render() → 生成 VNode → patch() → 根据 hostAPI 创建真实节点

示意:

scss 复制代码
VNode: { type:'rect', props:{x:10,y:20} }

↓ patch()

hostCreateElement(type)
hostPatchProp(node, key, value)
hostInsert(node, container)

DOM 变 Canvas,只要改 hostAPI 实现:

  • createElement → 创建 canvas shape
  • patchProp → 更新 shape 属性
  • insert → 加入 canvas 容器
  • remove → 删除 shape

核心渲染逻辑完全复用。


🎯 三、实战:创建一个 Canvas 渲染器(真正能运行的示例)

下面是一个可运行的最小 Canvas 渲染器:

typescript 复制代码
import { createRenderer, h } from 'vue'

const renderer = createRenderer({
  createElement(type) {
    return { type, x: 0, y: 0 }
  },
  patchProp(node, key, prev, next) {
    node[key] = next
  },
  insert(node, parent) {
    parent.children.push(node)
  },
  remove(node, parent) {
    parent.children = parent.children.filter(n => n !== node)
  },
  setElementText(node, text) {
    node.text = text
  }
})

const { createApp } = renderer

使用:

scss 复制代码
createApp({
  render() {
    return h('rect', { x: 10, y: 20 })
  }
}).mount(canvasRoot)

这里:

  • rect 不是 HTML element
  • 是我们自定义的 "图形节点"

真正的绘制由你来做。


🎯 四、现实场景(面试官喜欢的)

Vue3 渲染器能用来做:

  • WebGL 游戏引擎(已有 demo)
  • Canvas UI 库
  • 跨端框架(MiaoJS / UniApp)
  • Node 后端渲染(SSR)
  • 自定义 PDF、SVG 等渲染

比如:

  • Vue + PixiJS(游戏)
  • Vue + ThreeJS(3D)
  • Vue + WeChat 小程序(需要微信适配器)

🎯 五、面试官追问 + 高分回答


❓1:Vue3 runtime-core 和 runtime-dom 的关系是什么?

高分回答:

  • runtime-core:平台无关,只负责组件、vnode、diff。
  • runtime-dom:平台相关,只是提供 DOM API。

Vue3 的强大源于这个分层。


❓2:React 也能做自定义渲染器吗?对比 Vue?

你可以这样答:

React 也能(react-reconciler)

但难度更高、API 更复杂。

Vue3 优势:

  • 渲染器 API 更简单
  • diff 更解耦
  • runtime-core 更独立
  • 更适合跨端

高分总结:

React = 柔性更强,但复杂

Vue3 = 适配器更易写、成本更低


❓3:为什么 createRenderer 能支持 SSR?

因为 SSR 只是换了另一套 hostAPI:

  • createElement → createSSRNode
  • insert → appendToHTMLString
  • patchProp → 拼接 attribute 字符串

同样的 renderer + 不同 hostAPI → SSR、DOM、Canvas 通吃。


❓4:为什么 Vue3 可以同时存在 2 套 renderer?(SSR + CSR)

因为 renderer 是独立创建。

浏览器端:

scss 复制代码
createRenderer(domOperations)

SSR 端:

scss 复制代码
createRenderer(stringOperations)

renderer 实例独立互不干扰。


🎯 六、高分总结(背下来直接秒杀面试)

Vue3 通过 createRenderer 实现了"渲染层"和"平台层"的完全解耦。

虚拟 DOM、Diff、组件系统都是平台无关的,平台差异全部抽象为 hostAPI。

因此 Vue3 可以渲染到 DOM、Canvas、WebGL、小程序、Node SSR 等任何环境,是一个真正跨平台 UI 引擎。

相关推荐
前端一课1 小时前
【vue高频面试题】第 23 题:Vue3 自定义指令(directive)完整解析
前端·面试
前端一课1 小时前
第 28 题:Vue3 的 Diff 算法核心原理(双端 Diff、PatchFlags、Block Tree、静态提升)
前端·面试
前端一课1 小时前
【vue高频面试题】第 21 题:Vue3 中的 Slot(插槽)— 基础、原理、使用场景、面试必问点
前端·面试
前端一课1 小时前
第 24 题:Vue3 的组件通信方式(props / emit / v-model / provide-inject / expose / eventBus
前端·面试
前端一课1 小时前
第 22 题:Teleport 的作用、原理和使用场景
前端·面试
前端一课1 小时前
第 29 题:Vue3 的 Teleport 原理(跨层级 DOM 挂载技术)
前端·面试
前端一课1 小时前
第 31 题:Vue3 中 watchEffect 的原理(依赖自动追踪 + 清理机制 + ReactiveEffect 全流程)
前端·面试
前端一课1 小时前
第 256 题:Vue3 的异步组件(defineAsyncComponent)+ Suspense 原理与面试高频点
前端·面试
前端一课1 小时前
第 27 题:Vue3 + TS 类型推断(Props 类型推导、Emit 类型推导、Setup 返回值类型)
前端·面试