fix(food-encyclopedia): 修复点击食物卡片 item 为 undefined 的根因

根因:小程序编译时 @click="goToFoodDetail(item)" 通过 dataset 传递
复杂对象,scroll-view 内 DOM 回收或列表异步刷新后 dataset 序列化
丢失,导致 item 变为 undefined。

修复:
1. 模板改为 @click="handleFoodItemClick(index)" 传递基本类型
2. 新增 handleFoodItemClick 方法,从 filteredFoodList 实时取 item
3. foodRowKey 始终拼接 index 避免重复 id 导致 Vue DOM 复用错乱

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
msh-agent
2026-04-11 15:46:06 +08:00
parent 5b08211fa2
commit 19b6dc1d2b

View File

@@ -100,7 +100,7 @@
class="food-item"
v-for="(item, index) in filteredFoodList"
:key="foodRowKey(item, index)"
@click="goToFoodDetail(item)"
@click="handleFoodItemClick(index)"
>
<view class="food-image-wrapper">
<!-- 配图优先 item.imageUrl/img/imagenormalize 已对齐再经 displayFoodImage 拼域名与占位BUG-003 -->
@@ -272,11 +272,11 @@ export default {
this.loadFoodList();
},
methods: {
/** 列表 :key无效 id 曾为 '' 时多行共用同一 key导致点击与展示错乱 */
/** 列表 :key始终拼接 index 保证唯一,避免重复 id 导致 Vue DOM 复用错乱、点击传参丢失 */
foodRowKey(item, index) {
const id = item && item.id
const idStr = id !== undefined && id !== null && id !== '' ? String(id).trim() : ''
if (idStr !== '' && /^-?\d+$/.test(idStr)) return 'id-' + idStr
if (idStr !== '' && /^-?\d+$/.test(idStr)) return 'id-' + idStr + '-' + index
const n = item && item.name != null ? String(item.name).trim() : ''
return 'idx-' + index + '-' + (n || 'row')
},
@@ -1009,8 +1009,22 @@ export default {
}
}, 300);
},
/**
* 点击食物卡片的入口方法:通过 index 从 filteredFoodList 实时获取 item。
* 小程序编译时 @click="fn(item)" 会通过 dataset 传递复杂对象scroll-view 内
* DOM 回收或列表异步刷新后 dataset 可能丢失导致 item 为 undefined。
* 改为传递基本类型 index在方法内从响应式数据实时取值彻底解决此问题。
*/
handleFoodItemClick(index) {
const item = this.filteredFoodList[index]
if (!item || typeof item !== 'object') {
console.warn('[food-encyclopedia] handleFoodItemClick: index', index, '对应 item 为空filteredFoodList.length =', this.filteredFoodList.length)
return
}
this.goToFoodDetail(item)
},
goToFoodDetail(item) {
// 防御性校验:避免 item 为空时报错fix: TypeError Cannot read property 'id' of undefined
// 防御性校验(兜底,正常路径由 handleFoodItemClick 保证 item 有效
if (!item || typeof item !== 'object') {
console.warn('[food-encyclopedia] goToFoodDetail: item 为空,跳过跳转', item)
return