diff --git a/msh_single_uniapp/pages/tool/food-encyclopedia.vue b/msh_single_uniapp/pages/tool/food-encyclopedia.vue index 5c1dfca..6a64352 100644 --- a/msh_single_uniapp/pages/tool/food-encyclopedia.vue +++ b/msh_single_uniapp/pages/tool/food-encyclopedia.vue @@ -100,7 +100,7 @@ class="food-item" v-for="(item, index) in filteredFoodList" :key="foodRowKey(item, index)" - @click="goToFoodDetail(item)" + @click="handleFoodItemClick(index)" > @@ -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