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

Angular中如何将特定分类的图书数据从一个模块传递到另一个模块

实现方案

我们采用路由携带分类标识+目标页主动拉取数据的主流方案,优势是页面刷新后数据不会丢失,逻辑更稳定。如果不需要支持页面刷新、不想重复发起请求,可参考文末的公共服务缓存方案。


第一步:修改路由配置(app-routing.module.ts)

给目标页面路由新增分类名参数,用于传递选中的分类:

const routes: Routes = [
  // 其他原有路由保持不变
  { path: 'singlegenrebooks/:genreName', component: SinlegenrebooksComponent }
];

第二步:修改 genres.component.ts

注入路由服务,修改点击事件逻辑,移除重复的异步写法:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router'; // 新增导入
import { ApiService } from '../api.service';
import { Book } from '../books/bookschema';
import { Genres } from './genres_schema';

@Component({
  selector: 'app-genres',
  templateUrl: './genres.component.html',
  styleUrls: ['./genres.component.css'],
})
export class GenresComponent implements OnInit {
  GenreForm = new FormGroup({
    _id: new FormControl(''),
    name: new FormControl(''),
    floor: new FormControl(''),
    genre_number: new FormControl(''),
    shelves: new FormControl(''),
  });
  results?: Genres[];
  bookresults?: Book[];

  constructor(
    private readonly apiService: ApiService,
    private router: Router // 新增注入
  ) {}

  ngOnInit() {
    this.apiService.getallgenres().subscribe((data) => {
      this.results = data;
    });
  }

  // 修改后的点击方法:携带分类名跳转到目标页
  get_books_of_single_genre(genre: Genres) {
    // 编码分类名避免特殊字符导致路由异常
    this.router.navigate(['/singlegenrebooks', encodeURIComponent(genre.name)]);
  }
}

第三步:修改 genres.component.html

移除a标签上重复的routerLink属性,避免跳转冲突,同时把href="#"替换成javascript:void(0)防止点击跳转到页面顶部:

<div class="grid" *ngFor="let result of results">
    <div class="blog-card spring-fever">
      <div class="title-content">
        <h3>
          <a href="javascript:void(0)">{{ result?.name }}</a>
        </h3>
        <div class="intro"><a href="javascript:void(0)">Inspiration</a></div>
      </div>
      <div class="card-info">
        <a
          href="javascript:void(0)"
          (click)="get_books_of_single_genre(result)"
          >Enter<span class="licon icon-arr icon-black"></span
        ></a>
<!-- 其余原有代码保持不变 -->

第四步:修改 singlegenrebooks.component.ts

注入路由参数服务,在初始化时拿到分类名、拉取对应图书,同时实现搜索框过滤逻辑:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router'; // 新增导入ActivatedRoute
import { ApiService } from 'src/app/api.service';
import { Book } from 'src/app/books/bookschema';

@Component({
  selector: 'app-sinlegenrebooks',
  templateUrl: './sinlegenrebooks.component.html',
  styleUrls: ['./sinlegenrebooks.component.css'],
})
export class SinlegenrebooksComponent implements OnInit {
  SingleGenreBookForm = new FormGroup({
    _id: new FormControl(''),
    bid: new FormControl(''),
    name: new FormControl(''),
    author: new FormControl(''),
    price: new FormControl(''),
    genres_name: new FormControl(''),
  });
  rawResults?: Book[]; // 存储原始全量图书数据
  results?: Book[]; // 存储过滤后展示的图书数据
  searchedText: string = '';
  model: any;

  constructor(
    private readonly apiService: ApiService,
    private router: Router,
    private route: ActivatedRoute // 新增注入路由参数服务
  ) {}

  async ngOnInit() {
    // 从路由中获取分类名参数
    const genreName = decodeURIComponent(this.route.snapshot.paramMap.get('genreName') || '');
    if(genreName) {
      // 拉取对应分类的图书数据
      (await this.apiService.getallBooksofSingleGenere(genreName)).subscribe(
        (data) => {
          this.rawResults = data;
          this.results = data;
          this.bindSearchFilter(); // 绑定搜索过滤逻辑
        }
      );
    }
  }

  // 搜索框实时过滤逻辑
  bindSearchFilter() {
    const searchInput = document.querySelector('input[placeholder="Search Book by Name"]');
    searchInput?.addEventListener('input', () => {
      if(!this.rawResults) return;
      const keyword = this.searchedText.trim().toLowerCase();
      // 搜索关键词为空时展示全量数据
      if(!keyword) {
        this.results = [...this.rawResults];
        return;
      }
      // 按图书名模糊匹配过滤
      this.results = this.rawResults.filter(book => 
        book.name?.toLowerCase().includes(keyword)
      );
    })
  }
}

第五步:修改 singlegenrebooks.component.html

新增空状态提示,避免无数据时页面空白:

<!-- 原有导航栏代码保持不变 -->
<div class="background">
  <div class="d-flex justify-content-center">
    <button
      style="margin-top: 1%"
      type="button"
      class="btn btn-success btn-block btn-lg gradient-custom-4 text-body"
      routerLink="/"
    >
      Go Back
    </button>
    <button
      style="margin-left: 60%; margin-top: 1%"
      type="button"
      class="btn btn-success btn-block btn-lg gradient-custom-4 text-body"
      routerLink="/adbooksroute"
    >
      Add Books
    </button>
  </div>
  <!-- 新增空状态提示 -->
  <div *ngIf="!results || results.length === 0" class="text-center mt-5">
    <h4>暂无该分类下的图书</h4>
  </div>
  <!-- 原有列表逻辑:只有有数据时才渲染 -->
  <div *ngIf="results && results.length > 0">
    <div class="grid" *ngFor="let result of results">
      <!-- 原有卡片代码保持不变 -->
    </div>
  </div>
</div>

可选:公共服务缓存方案(无需重复发请求)

如果不需要支持页面刷新,可通过全局公共服务缓存选中分类的图书数据,避免重复发起请求:

  1. 新建genre-data.service.ts存储公共数据:
import { Injectable } from '@angular/core';
import { Book } from './books/bookschema';

@Injectable({ providedIn: 'root' })
export class GenreDataService {
  selectedGenreBooks: Book[] = [];
}
  1. 在genres.component.ts中拿到图书数据后存入服务再跳转
  2. 在singlegenrebooks.component.ts中直接从服务取数据即可,无需再发请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:54:01