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

Angular鼠标悬停渲染Card组件并展示详情的实现方案咨询

Angular 鼠标悬停加载卡片详情组件实现方案

我已经掌握Angular组件创建、API数据获取、*ng指令使用等技能,目前遇到技术瓶颈:
现有Hand(父组件)和Card(子组件)两个组件,Hand组件通过CardDataService的getAllCards()接口随机获取5条卡片数据并展示;需求为鼠标悬停Hand组件内的卡片时,调用CardDataService的getCardById()接口获取对应ID的详细数据,渲染Card组件展示详情,鼠标离开时销毁该组件渲染。尝试过@Input指令但未能实现ID传递与组件渲染,寻求可行实现方案。


先修复原代码中的基础错误

这些问题是导致功能无法正常运行的前提:

  • Hand组件的selector写错为app-card,与Card组件冲突,需改为app-hand
  • Card组件未注入CardDataService,且getCardData方法参数传递逻辑错误
  • Hand组件初始化时调用的方法名不匹配,导致卡片数据无法加载
  • Card组件模板中img标签存在语法错误,缺少闭合双引号
  • 未绑定鼠标悬停/离开事件,也没有控制Card组件显示状态的逻辑

完整实现方案

1. 修改 hand.component.ts

修正组件标识、注入服务、添加事件处理逻辑:

import { Component, OnInit } from '@angular/core';
import { CardDataService } from '../../services/card-data.service';

@Component({
    selector: 'app-hand', // 修正组件选择器
    templateUrl: './hand.component.html',
    styleUrls: ['./hand.component.scss'],
})
export class HandComponent implements OnInit{
    hand: any[] = [];
    hoveredCardId: number | null = null; // 存储当前悬停卡片的ID

    constructor(private cardDataService: CardDataService) { }

    ngOnInit(): void {
        this.getAllCards(); // 调用正确的加载方法
    }

    public getAllCards() {
        this.cardDataService.getAllCards().subscribe((response: any) => {
            // 优化随机选卡逻辑,避免重复选取
            const cardList = [...response];
            for (let i = 0; i < 5 && cardList.length > 0; i++) {
                const randomIndex = Math.floor(Math.random() * cardList.length);
                this.hand.push(cardList.splice(randomIndex, 1)[0]);
            }
            console.log(this.hand);
        });
    }

    // 鼠标悬停时记录当前卡片ID
    onCardHover(id: number) {
        this.hoveredCardId = id;
    }

    // 鼠标离开时清空ID,销毁子组件
    onCardLeave() {
        this.hoveredCardId = null;
    }
}

2. 修改 hand.component.html

绑定鼠标事件,添加Card组件的条件渲染:

<ng-container *ngFor="let item of hand">
  <div class="card-hand" 
       (mouseenter)="onCardHover(item.id)" 
       (mouseleave)="onCardLeave()">
    <p>CARD {{ item.id }}</p>
    <img [src]="item.picture">
    <p>{{ item.element }}</p>
  </div>
</ng-container>

<!-- 仅当hoveredCardId存在时,渲染Card子组件并传递ID -->
<app-card *ngIf="hoveredCardId" [cardId]="hoveredCardId"></app-card>

3. 修改 card.component.ts

添加@Input接收ID,监听ID变化自动加载详情:

import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { CardDataService } from '../../services/card-data.service';

@Component({
    selector: 'app-card',
    templateUrl: './card.component.html',
    styleUrls: ['./card.component.scss'],
})
export class CardComponent implements OnInit, OnChanges{
    @Input() cardId!: number; // 接收父组件传递的卡片ID
    public item?: any;

    constructor(private cardDataService: CardDataService) { }

    ngOnInit(): void {
        this.loadCardDetails();
    }

    // 监听cardId变化,自动重新加载详情
    ngOnChanges(changes: SimpleChanges): void {
        if (changes['cardId'] && changes['cardId'].currentValue) {
            this.loadCardDetails();
        }
    }

    private loadCardDetails() {
        this.cardDataService.getCardById(this.cardId).subscribe((response: any) => {
            this.item = response;
        });
    }
}

4. 修改 card.component.html

修复语法错误,添加空值避免报错:

<div *ngIf="item" class="card-display">
  <p>CARD {{ item.id }}</p>
  <p>LEVEL {{ item.level }}</p>
  <img [src]="item.picture">
  <p>{{ item.description }}</p>
  <div class="card-stats">
    <label>{{ item.attack }}</label>
    <label>{{ item.defense }}</label>
  </div>
</div>

方案核心逻辑说明

  1. 组件渲染控制:通过父组件的hoveredCardId变量结合*ngIf指令,实现Card组件的动态创建与销毁,鼠标离开时清空ID即可自动销毁组件
  2. 数据传递:使用@Input()将父组件的悬停卡片ID传递给子组件,子组件通过OnChanges钩子监听ID变化,自动触发详情加载
  3. 事件绑定:为每个卡片容器绑定mouseenter和mouseleave事件,实时更新当前悬停的卡片ID
  4. 代码优化:修复原代码的语法与逻辑错误,使用属性绑定[src]替代插值表达式提升安全性,优化随机选卡逻辑避免重复选取

内容的提问来源于stack exchange,提问作者David Encina Martínez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:32:50