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>
可选:公共服务缓存方案(无需重复发请求)
如果不需要支持页面刷新,可通过全局公共服务缓存选中分类的图书数据,避免重复发起请求:
- 新建
genre-data.service.ts存储公共数据:
import { Injectable } from '@angular/core'; import { Book } from './books/bookschema'; @Injectable({ providedIn: 'root' }) export class GenreDataService { selectedGenreBooks: Book[] = []; }
- 在
genres.component.ts中拿到图书数据后存入服务再跳转 - 在
singlegenrebooks.component.ts中直接从服务取数据即可,无需再发请求
内容的提问来源于stack exchange,提问作者M Nouman
相关产品推荐
相关产品推荐

