You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:44:37