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:
@@ -100,7 +100,7 @@
|
|||||||
class="food-item"
|
class="food-item"
|
||||||
v-for="(item, index) in filteredFoodList"
|
v-for="(item, index) in filteredFoodList"
|
||||||
:key="foodRowKey(item, index)"
|
:key="foodRowKey(item, index)"
|
||||||
@click="goToFoodDetail(item)"
|
@click="handleFoodItemClick(index)"
|
||||||
>
|
>
|
||||||
<view class="food-image-wrapper">
|
<view class="food-image-wrapper">
|
||||||
<!-- 配图:优先 item.imageUrl/img/image(normalize 已对齐),再经 displayFoodImage 拼域名与占位(BUG-003) -->
|
<!-- 配图:优先 item.imageUrl/img/image(normalize 已对齐),再经 displayFoodImage 拼域名与占位(BUG-003) -->
|
||||||
@@ -272,11 +272,11 @@ export default {
|
|||||||
this.loadFoodList();
|
this.loadFoodList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 列表 :key:无效 id 曾为 '' 时多行共用同一 key,导致点击与展示错乱 */
|
/** 列表 :key:始终拼接 index 保证唯一,避免重复 id 导致 Vue DOM 复用错乱、点击传参丢失 */
|
||||||
foodRowKey(item, index) {
|
foodRowKey(item, index) {
|
||||||
const id = item && item.id
|
const id = item && item.id
|
||||||
const idStr = id !== undefined && id !== null && id !== '' ? String(id).trim() : ''
|
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() : ''
|
const n = item && item.name != null ? String(item.name).trim() : ''
|
||||||
return 'idx-' + index + '-' + (n || 'row')
|
return 'idx-' + index + '-' + (n || 'row')
|
||||||
},
|
},
|
||||||
@@ -1009,8 +1009,22 @@ export default {
|
|||||||
}
|
}
|
||||||
}, 300);
|
}, 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) {
|
goToFoodDetail(item) {
|
||||||
// 防御性校验:避免 item 为空时报错(fix: TypeError Cannot read property 'id' of undefined)
|
// 防御性校验(兜底,正常路径由 handleFoodItemClick 保证 item 有效)
|
||||||
if (!item || typeof item !== 'object') {
|
if (!item || typeof item !== 'object') {
|
||||||
console.warn('[food-encyclopedia] goToFoodDetail: item 为空,跳过跳转', item)
|
console.warn('[food-encyclopedia] goToFoodDetail: item 为空,跳过跳转', item)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user