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

Angular项目JS转TS后BMI组件无报错但无法运行问题求助

解决Angular项目中BMI组件无法运行的问题

我看了你的代码,发现核心问题是你把AngularJS(1.x)的代码逻辑直接硬塞进了Angular(2+)的TypeScript组件里——这俩是完全不同的框架,语法和运行机制不兼容,难怪项目在包含这个组件时跑不起来。我帮你把代码改成符合Angular规范的写法,同时保留原来的卡路里计算器功能:

修正后的 bmi.component.ts

import { Component, OnInit } from '@angular/core';

// 定义类型接口,避免滥用any
interface Activity {
  name: string;
  multiply: number;
}

interface Goal {
  name: string;
  alt: string;
  cals: number;
}

interface MealNutrient {
  name: string;
  value: () => number;
}

@Component({
  selector: 'app-bmi',
  templateUrl: './bmi.component.html',
  styleUrls: ['./bmi.component.css']
})
export class BmiComponent implements OnInit {
  // 替代原$scope的组件属性
  activities: Activity[] = [
    {name: 'Little to no exercise', multiply: 1.2},
    {name: 'Light exercise (1–3 days per week)', multiply: 1.375},
    {name: 'Moderate exercise (3–5 days per week)', multiply: 1.55},
    {name: 'Heavy exercise (6–7 days per week)', multiply: 1.725},
    {name: 'Very heavy exercise (twice per day, extra heavy workouts)', multiply: 1.9}
  ];

  goals: Goal[] = [
    {name: 'Lose weight - 1lb per week', alt: 'tone', cals: 500},
    {name: 'Lose weight - 2lb per week', alt: 'tone', cals: 1000},
    {name: 'Gain weight - 1lb per week', alt: 'bulk', cals: -500},
    {name: 'Gain weight - 2lb per week', alt: 'bulk',cals: -1000},
    {name: 'Maintain weight', alt: 'tone', cals: 0}
  ];

  // 用户输入的参数
  gender: 'male' | 'female' | undefined;
  weight: string = '';
  height: string = '';
  age: string = '';
  selectedActivity: Activity | undefined;
  selectedGoal: Goal | undefined;

  constructor() { }

  ngOnInit(): void {
  }

  // 计算BMR的方法
  bmr(): number | undefined {
    const weightNum = parseInt(this.weight, 10);
    const heightNum = parseInt(this.height, 10);
    const ageNum = parseInt(this.age, 10);

    // 先检查输入是否有效
    if (isNaN(weightNum) || isNaN(heightNum) || isNaN(ageNum) || !this.gender) {
      return undefined;
    }

    const standard = weightNum * 10 + heightNum * 6.25 - ageNum * 5;
    if (this.gender === 'male') {
      return standard + 5;
    } else {
      return standard - 161;
    }
  }

  // 计算每日卡路里
  cals(): number | undefined {
    const bmrValue = this.bmr();
    if (bmrValue && this.selectedActivity && this.selectedGoal) {
      return bmrValue * this.selectedActivity.multiply - this.selectedGoal.cals;
    }
    return undefined;
  }

  // 蛋白质卡路里
  proteinCals(): number | undefined {
    const totalCals = this.cals();
    return totalCals ? totalCals * 0.55 : undefined;
  }

  // 碳水卡路里
  carbsCals(): number | undefined {
    const totalCals = this.cals();
    return totalCals ? totalCals * 0.25 : undefined;
  }

  // 脂肪卡路里
  fatCals(): number | undefined {
    const totalCals = this.cals();
    return totalCals ? totalCals * 0.2 : undefined;
  }

  // 各餐营养分配
  get breakfast(): MealNutrient[] {
    return [
      {name: 'protein', value: () => this.proteinCals() ? (this.proteinCals()! * 0.0252) / 4 : 0},
      {name: 'carbs', value: () => this.carbsCals() ? (this.carbsCals()! * 0.0933) / 4 : 0},
      {name: 'fat', value: () => this.fatCals() ? (this.fatCals()! * 0.3467) / 8 : 0}
    ];
  }

  get snack(): MealNutrient[] {
    return [
      {name: 'protein', value: () => this.proteinCals() ? (this.proteinCals()! * 0.0573) / 4 : 0},
      {name: 'carbs', value: () => this.carbsCals() ? (this.carbsCals()! * 0.1295) / 4 : 0},
      {name: 'fat', value: () => this.fatCals() ? (this.fatCals()! * 0.04) / 8 : 0}
    ];
  }

  get mainMeal(): MealNutrient[] {
    return [
      {name: 'protein', value: () => this.proteinCals() ? (this.proteinCals()! * 0.4014) / 4 : 0},
      {name: 'carbs', value: () => this.carbsCals() ? (this.carbsCals()! * 0.2591) / 4 : 0},
      {name: 'fat', value: () => this.fatCals() ? (this.fatCals()! * 0.2666) / 8 : 0}
    ];
  }
}

配套的 bmi.component.html 示例

<div class="calculator-container">
  <!-- 用户输入区域 -->
  <div class="input-section">
    <div>
      <label>Gender:</label>
      <select [(ngModel)]="gender">
        <option value="male">Male</option>
        <option value="female">Female</option>
      </select>
    </div>
    <div>
      <label>Weight (lbs):</label>
      <input type="number" [(ngModel)]="weight" placeholder="Enter weight">
    </div>
    <div>
      <label>Height (inches):</label>
      <input type="number" [(ngModel)]="height" placeholder="Enter height">
    </div>
    <div>
      <label>Age:</label>
      <input type="number" [(ngModel)]="age" placeholder="Enter age">
    </div>
    <div>
      <label>Activity Level:</label>
      <select [(ngModel)]="selectedActivity">
        <option *ngFor="let activity of activities" [ngValue]="activity">{{activity.name}}</option>
      </select>
    </div>
    <div>
      <label>Goal:</label>
      <select [(ngModel)]="selectedGoal">
        <option *ngFor="let goal of goals" [ngValue]="goal">{{goal.name}}</option>
      </select>
    </div>
  </div>

  <!-- 结果展示区域 -->
  <div class="results-section" *ngIf="cals()">
    <h3>Your Daily Calorie Target: {{cals() | number}}</h3>
    <div class="nutrient-breakdown">
      <p>Protein: {{proteinCals() | number}} cals</p>
      <p>Carbs: {{carbsCals() | number}} cals</p>
      <p>Fat: {{fatCals() | number}} cals</p>
    </div>

    <h4>Meal Breakdown</h4>
    <div class="meal-section">
      <h5>Breakfast</h5>
      <p *ngFor="let item of breakfast">{{item.name}}: {{item.value() | number}}g</p>
    </div>
    <div class="meal-section">
      <h5>Snack</h5>
      <p *ngFor="let item of snack">{{item.name}}: {{item.value() | number}}g</p>
    </div>
    <div class="meal-section">
      <h5>Main Meal</h5>
      <p *ngFor="let item of mainMeal">{{item.name}}: {{item.value() | number}}g</p>
    </div>
  </div>
</div>

关键修改说明

  • 移除AngularJS遗留代码:删掉了BmiComponent.module和app.controller这些AngularJS专属语法,Angular(2+)完全基于组件类来管理逻辑和状态。
  • 添加TypeScript类型定义:创建了Activity、Goal等接口,给组件属性和方法指定明确类型,避免any类型带来的潜在问题。
  • 替换$scope为组件属性:原来绑定在$scope上的变量和方法,全部改成组件类的成员,Angular通过双向绑定([(ngModel)])和模板插值来访问这些属性。
  • 修正类型检查逻辑:把错误的Number(...) !== NaN改成!isNaN(),因为NaN和任何值比较结果都是false,无法正确判断是否为有效数字。
  • 优化计算方法:给所有计算方法添加了空值检查,避免出现undefined导致的模板渲染错误。

内容的提问来源于stack exchange,提问作者karthik eyan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:35:37