一次:key 表达式导致的uni-app小程序事件传参事故

发布时间:2026/8/25 13:06:43
一次:key 表达式导致的uni-app小程序事件传参事故 一、问题重现!-- DOM示例 -- view v-for(item,index) in list :keyitem.id || index view clickgoSign(item)签署协议/view /view !-- JS示例 -- goSign(item){ console.log(item) // undefined }最近在 uni-app 项目里遇到一个很隐蔽的问题列表页点击“签署协议”时方法明明写的是clickgoSign(item)正常来说item是可以获取到值的。但是实际在uni-app中goSign函数的item居然是undefined。二、问题分析第一反应通常会怀疑事件绑定、数据接口、组件层级甚至怀疑是不是某个 SDK 影响了运行。但最后排查下来问题出在一个非常不起眼的地方view v-for(item,index) in list :keyitem.id || index在 H5 / 普通 Vue 里这种写法一般没问题。item.id || index会作为表达式正常执行goSign(item)也能拿到当前循环项。但 uni-app 编译到微信小程序时事情不完全一样。微信小程序模板没有 Vue 那种完整的 JS 闭包能力。uni-app 为了支持v-for里的事件传参会在编译阶段生成一套“根据列表和 key 回查原始 item”的逻辑。当我们写:keyitem.id || indexuni-app 可能会把它处理成类似[list, id||index, item.id || index]也就是说它没有把item.id || index当成一个运行时表达式重新执行而是把中间的id||index当成了字段路径。运行时再去列表里找row[id||index]但真实数据里当然没有一个叫id||index的字段于是回查失败事件参数里的item就变成了undefined。三、修复建议不要在小程序端的v-for :key里写复杂表达式提前把 key 算成一个真实字段this.list result.data.map((item, index) ({ ...item, rowKey: item.id || index }))DOM里改成view v-for(item, index) in list :keyitem.rowKey view clickgoSign(item)签署协议/view /view这次问题的教训是uni-app 虽然写起来像 Vue但目标平台是小程序时模板表达式、事件传参、v-for key并不总是等价于浏览器里的 Vue 行为。在小程序端最稳的写法永远是让key指向一个真实、稳定、简单的字段。