0

0

如何手动构建 VNode 属性对象?避开渲染函数中 Data 结构变化的坑

冰川箭仙

冰川箭仙

发布时间:2026-03-18 10:07:44

|

338人浏览过

|

来源于php中文网

原创

手动构建 VNode 属性对象需严格区分响应式数据与静态属性:class/style 必须解包为纯 JS 值;事件处理器须用稳定函数引用;directives 和 slots 需单独传参;props 对象本身不可响应式。

如何手动构建 vnode 属性对象?避开渲染函数中 data 结构变化的坑

手动构建 VNode 属性对象,核心是理解 Vue 3 中 VNodeProps 的结构规范,并严格区分“响应式数据”与“静态属性”的注入时机。关键不是堆砌字段,而是按 Vue 内部解析逻辑组织键名和值类型——尤其要避开把响应式对象直接赋给 classstyle 或事件处理器等需特殊处理的字段。

class 和 style 必须用规范化格式,不能传响应式对象

classstyle 在 VNode props 中虽是字符串键,但 Vue 会做深度归一化:它期望接收的是数组、对象或字符串,而非一个 refreactive 包裹的值。若你传入 class: reactive({ active: isActived }),Vue 不会自动追踪其变化,渲染时取到的仍是初始快照。

  • ✅ 正确做法:在构建 props 对象前,先解包响应式值,生成纯 JS 值
  • 例如:const cls = [baseClass, { 'is-active': isActived.value }],再传入 { class: cls }
  • ✅ style 同理:用 { color: textColor.value, fontSize: `${size.value}px` },而不是 style: reactive({ ... })

事件监听器必须是函数引用,不可包裹或延迟求值

Vue 在 patch 阶段比对事件时,依赖函数引用相等性(===)判断是否更新。若每次构建 props 都写 onClick: () => handleClick()onClick: handleClick.bind(null, id),会导致每次生成新函数,强制重绑事件,丢失 DOM 事件缓存,还可能引发内存泄漏。

  • ✅ 正确做法:提前定义稳定函数引用,必要时用闭包捕获参数
  • 例如:const handleClickItem = (id) => { /* ... */ }; const props = { onClick: () => handleClickItem(itemId) };
  • ⚠️ 注意:不要在 render 函数里动态创建箭头函数作为事件处理器

指令(directives)和插槽(slots)不能混进 data 对象

Vue 3 的 VNode 构造函数(如 createVNode)明确将 propsdirectivesslots 分离为不同参数。若把 v-loading 指令写成 { 'v-loading': true } 放进 props,它不会生效;同理,插槽函数也不能塞进 props.children

  • ✅ 指令应单独传入第 4 个参数:createVNode(Component, props, slots, { directives: [{ name: 'loading', value: isLoading }] })
  • ✅ 插槽必须作为独立参数传入,且需符合函数签名:slots: { default: () => [/* VNodes */] }
  • ⚠️ keyrefclassstyle 等属于 props;onXXX 事件也属 props,但 v-xxx 不是

避免用响应式对象直接覆盖整个 props 对象

有些开发者会写 const props = reactive({ class: ..., onClick: ... }); createVNode(..., props),这看似简洁,实则危险:Vue 不会对整个 props 对象做响应式代理监听,只读取构建瞬间的值;后续 props.class 变更不会触发 VNode 更新。

  • ✅ 正确策略:props 对象本身保持普通(non-reactive),仅内部字段值可来自响应式源,且需手动同步
  • ✅ 更稳妥方式:在 render 函数中每次重新计算 props,确保所有字段都是最新纯值
  • 例如:return () => createVNode('div', { class: computeClass(), onClick: handleClick })

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
vue.js为什么报错
vue.js为什么报错

vue.js报错的原因:1、语法错误;2、组件使用不当;3、数据绑定问题;4、生命周期钩子使用不当;5、插件或依赖问题;6、路由配置错误;7、异步操作处理不当等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

129

2024.03.11

vue.js插槽有哪些用
vue.js插槽有哪些用

vue.js插槽的作用:1、提高组件的可重用性;2、实现组件的灵活布局;3、实现组件间的数据传递和交互;4、促进组件的解耦和模块化。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

187

2024.03.11

vue.js怎么带参数跳转
vue.js怎么带参数跳转

vue.js带参数跳转的方法:1、定义路由;2、在组件中使用路由参数;3、进行带参数的跳转。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

98

2024.03.11

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

256

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1154

2024.03.01

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

565

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

17

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号