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

Angular中通过emit向子组件传递对象的实现及报错排查

问题产生原因
  • 组件通信装饰器用反:Angular中@Input()用于父组件向子组件传值,向外抛出事件、传递数据必须用@Output()搭配EventEmitter,原代码把addProduct事件发射器声明为@Input属性,完全不符合通信规则。
  • 事件绑定对象错误:原代码在父组件中给购物车子组件<app-cart>绑定了addProduct事件,但这个事件根本不是CartComponent声明的输出事件,Angular无法识别自定义事件参数类型,会默认将$event解析为原生DOM的Event对象,和方法要求的Item类型不匹配,直接触发TS类型报错。
  • 组件模板存在冗余结构:Angular组件模板只需要保留自身渲染的片段,不需要写<!DOCTYPE html>、<html>、<head>、<body>这类全局页面标签,多余标签会引发渲染异常。
  • 属性绑定写法不规范:模板里的图片src用了插值写法,页面初始化时会出现无效资源请求。
正确实现方案

1. 修正商品项组件(ItemComponent)逻辑

将addProduct的装饰器从@Input改为@Output,声明为对外抛出的事件:

import { Component, Output, EventEmitter } from '@angular/core';
import { Item } from 'src/app/Model/Item';
import { StoreService } from 'src/app/service/store.service';
@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css']
})
export class ItemComponent  {
  items: Item[] = []
  // 用@Output声明对外抛出的加购事件
  @Output() addProduct: EventEmitter<Item> = new EventEmitter()
  constructor(private storeService: StoreService) {
    this.items = this.storeService.getItem()
  }

  addProducts(item: Item) {
    const product: Item = {
      id: item.id,
      img: item.img,
      name: item.name,
      type: item.type,
      price: item.price,
      available: item.available
    }
    // 点击按钮时向外抛出商品对象
    this.addProduct.emit(product)
  }
}

清理组件模板里的冗余全局标签,把图片src改成属性绑定写法:

<section>
  <div class="products">
    <ul *ngFor="let item of items">
      <img [routerLink]="['/product', item.id]" [src]="item.img" alt="store pictures"/>
      <li>{{item.name}}</li>
      <li>{{item.type}}</li>
      <li>{{item.available}}</li>
      <li>{{item.price}}</li>
      <button (click)="addProducts(item)">Add to Cart</button>
    </ul>
  </div>
</section>

2. 调整父组件的绑定逻辑

ItemComponent和CartComponent是平级的兄弟组件,需要父组件做通信中转:给CartComponent加模板引用变量,监听ItemComponent抛出的加购事件,拿到商品对象后直接调用CartComponent的加购方法即可。父组件模板代码如下:

<!-- 监听商品项组件抛出的加购事件,把拿到的商品传给购物车组件的加购方法 -->
<app-item (addProduct)="cart.addProduct($event)"></app-item>
<!-- 给购物车组件加模板变量#cart,代表组件实例 -->
<app-cart #cart></app-cart>

3. 保留购物车组件(CartComponent)原有逻辑

CartComponent里的加购方法本身逻辑正确,不需要修改:

import { Component, OnInit } from '@angular/core';
import { Item } from 'src/app/Model/Item';

@Component({
  selector: 'app-cart',
  templateUrl: './cart.component.html',
  styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit {
  product: Item[] = []
  ngOnInit(): void {
  }

  addProduct(post: Item){
    this.product.push(post)
  }
}
关键注意点
  • Angular组件通信方向要记清:@Input负责父到子传值,@Output + EventEmitter负责子到父抛事件,兄弟组件通信可以通过父组件中转,也可以用共享服务实现。
  • 只有组件用@Output声明过的事件,在模板上绑定的时候$event才会是你指定的泛型类型,否则Angular会默认按原生DOM事件解析,触发类型不匹配错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:48:46