Angular家庭预算追踪器报错:无法读取undefined的'food'属性
解决Angular中ngModel绑定滑块时“Cannot read property 'food' of undefined”错误
这个错误的核心原因很明确:你的组件中的budget对象变成了undefined,导致模板无法访问budget.food属性。让我们一步步拆解问题和解决方案:
问题根源
在组件的ngOnInit生命周期钩子中,你调用了this.service.getMonth(new Date().getMonth())并把返回值赋值给this.budget。但看你的BudgetService中的getMonth方法:
- 如果
localStorage里没有存储任何预算数据(budgets == null),方法没有返回值,默认返回undefined - 如果
budgets存在,但找不到对应月份的预算项,方法同样没有返回值,还是返回undefined
当this.budget被赋值为undefined后,模板里的[(ngModel)]="budget.food"自然会抛出“Cannot read property 'food' of undefined”的错误。
解决方案
1. 修复BudgetService的getMonth方法,确保始终返回有效的budget对象
修改getMonth方法,当找不到对应月份的预算时,返回一个结构完整的默认budget对象,这样组件里的this.budget永远不会是undefined:
getMonth = (month: number): budget => { let budgets: budget[] = JSON.parse(localStorage.getItem("budgets")); if (budgets != null) { for (let budget of budgets) { if (budget.month == month) { return budget; } } } // 当找不到对应月份时,返回默认的budget对象 return { month: month, income: 0, food: 0, drinks: 0, housing: 0, bills: 0, loans: 0, travel: 0, clothing: 0, insurances: 0, netflix: 0, hobby: 0, other: 0, date: new Date().getTime() } as budget; }
2. 修复save方法的逻辑漏洞
当前的save方法还有一个小问题:如果budgets数组已经存在,但没有当前月份的预算项,它不会添加新的预算。我们可以用findIndex来检查并处理这种情况:
save = (form: budget) => { let month: budget = { "month": form.month, "income": form.income, "food": form.food, "drinks": form.drinks, "housing": form.housing, "bills": form.bills, "loans": form.loans, "travel": form.travel, "clothing": form.clothing, "insurances": form.insurances, "netflix": form.netflix, "hobby": form.hobby, "other": form.other, "date": new Date().getTime() }; let budgets: budget[] = JSON.parse(localStorage.getItem("budgets")); if (budgets == null) { budgets = []; budgets.push(month); localStorage.setItem("budgets", JSON.stringify(budgets)); } else { // 查找是否存在对应月份的预算 const existingBudgetIndex = budgets.findIndex(budget => budget.month === form.month); if (existingBudgetIndex !== -1) { // 更新已有预算 budgets[existingBudgetIndex] = month; } else { // 添加新的预算 budgets.push(month); } localStorage.setItem("budgets", JSON.stringify(budgets)); } }
额外优化(可选)
你组件里定义的初始budget对象现在可以简化,因为getMonth方法已经会返回默认值了:
budget: budget; // 只需要声明类型即可
这样修改后,无论localStorage里有没有数据,你的budget对象都会是一个有效的实例,模板绑定就能正常工作,滑块的值也能正确保存和回显到localStorage了。
内容的提问来源于stack exchange,提问作者aleksejjj
相关产品推荐
相关产品推荐

