Vue渲染函数依赖组件实例或setup上下文访问响应式数据,读取时自动收集依赖,数据变更后触发重渲染生成新VNode,再经diff与patch更新DOM。

Vue 的渲染函数不是孤立运行的,它依赖一个明确的上下文环境来访问组件数据、方法、插槽和响应式状态。这个上下文决定了 render 函数如何读取数据、触发更新,并与 Vue 的双向绑定机制协同工作。
渲染函数的上下文对象(即参数)
render 函数接收一个函数作为参数,通常命名为 h(即 createElement),但它本身不直接提供数据访问能力。真正承载上下文的是组件实例(Vue 2)或 setup 返回的对象(Vue 3)。在 render 中,你通过 this(Vue 2)或显式传入的 ctx(Vue 3 的组合式 API 渲染函数)获取所需内容:
- data、props、computed:全部挂载在 this 上(Vue 2),或由 setup 返回后通过 ctx 访问(Vue 3)
- methods 和事件处理器:可直接调用 this.handleClick 或 ctx.handleClick
- 插槽内容:通过 this.$slots(Vue 2)或 ctx.slots(Vue 3)获取,支持具名插槽和作用域插槽
- 响应式依赖自动追踪:只要在 render 中读取了 this.msg 或 ctx.count,就会被当前组件的 Watcher 收集为依赖,后续变更时触发重渲染
数据绑定在 render 函数中如何生效
模板中的 v-model、:class、{{ msg }} 等语法糖,在 render 函数中需手动还原为等效逻辑。数据绑定的本质是「读取响应式属性 + 绑定更新回调」:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 单向绑定(显示):直接读取 this.msg,其 getter 触发依赖收集;值变化时 Watcher 重新执行 render
-
双向绑定(表单):需手动组合
:value和@input,例如:h('input', { props: { value: this.msg }, on: { input: e => this.msg = e.target.value } }) -
动态属性绑定:把对象传入第二个参数的
attrs或props字段,如{ class: { active: this.isActive } }
为什么 render 函数也能响应式更新
关键不在 render 函数本身,而在于它运行时所处的「响应式执行环境」:
立即学习“前端免费学习笔记(深入)”;
- 每个组件实例初始化时,会创建一个专属的 渲染 Watcher
- 首次调用 render 时,this 上所有响应式属性的 getter 被触发,Watcher 将自己记录进对应属性的 Dep 中
- 当 this.msg 被赋新值,setter 触发,Dep 通知该 Watcher;Watcher 在 nextTick 中异步重新执行 render,生成新 VNode 并 diff 更新 DOM
- 因此,哪怕你完全不用模板、只写 render,只要访问了响应式数据,整个响应式链条就已接入
注意事项与常见误区
render 函数灵活,但容易绕过 Vue 的约定导致绑定失效:
- 避免在 render 中使用未声明的变量或未响应式的普通对象属性(如 this.obj.newKey = 'x'),Vue 2 不会侦测,Vue 3 Proxy 虽能代理新增属性,但若未在 setup 初始返回,仍可能丢失响应性
- 不要在 render 中直接修改 data(如 this.count++),应封装为 methods 或 computed,保持渲染函数的纯函数特性
- 插槽默认内容需显式展开,
this.$slots.default是 VNode 数组,不能直接当作字符串拼接 - JSX 用户注意:JSX 编译后仍转为 h() 调用,上下文规则与 render 函数一致,只是写法更接近 HTML

















