Angular Observable,在组件内共享数据
Posted
技术标签:
【中文标题】Angular Observable,在组件内共享数据【英文标题】:Angular Observable, sharing data within components 【发布时间】:2018-12-22 22:15:51 【问题描述】:我正在 Angular 上制作我的第一个应用程序。我试图按性别属性过滤书籍对象列表。我在组件之间共享数据时遇到困难:filteredData
变量和书籍列表FireBaseList
。
我正在尝试将filteredData
变量从fixed-nav.component
传递给books-grid.component
。根据我的研究,我知道我需要使 books-grid.component
"bookList" 可观察到任何更改,并让 fixed-nav.component.ts
上的 bookList
在 this.bookList
上的任何更改上发出事件
但是,我无法做到这一点。我知道已经有很多关于 observables 的问题,但没有一个使用 Firebase。希望有大神能帮帮我,谢谢!!
我用作过滤器的fixed-nav.component
import Component, OnInit from '@angular/core';
import BookService from '../../../services/book.service';
import Book from '../../../models/book';
@Component(
selector: 'fixed-nav',
templateUrl: './fixed-nav.component.html',
styleUrls: ['./fixed-nav.component.css']
)
export class FixedNavComponent implements OnInit
Genders: string[];
bookList: Book[];
constructor(private bookService: BookService)
this.Genders = ["Historia","Literatura", "Infantil", "Juvenil","Poesía","Narrativa"];
filterByGender(gender: string)
this.bookService.getBooks() // FIREBASE
.snapshotChanges()
.subscribe(item =>
this.bookList = [];
item.forEach(element =>
let x = element.payload.toJSON();
x["$key"] = element.key;
this.bookList.push(x as Book)
)
const filteredData = this.bookList.filter( function(element)
return element.gender == gender;
);
return filteredData; // I WANT TO SHARE THIS DATA
)
ngOnInit()
books-grid.component.ts
import Component, OnInit from '@angular/core';
import BookService from '../../services/book.service';
import Book from '../../models/book';
@Component(
templateUrl: './books-grid.component.html',
styleUrls: ['./books-grid.component.css']
)
export class BooksGridComponent implements OnInit
bookList: Book[];
constructor(private bookService: BookService)
ngOnInit()
this.bookService.getBooks() // FIREBASE
.snapshotChanges()
.subscribe(item =>
this.bookList = [];
item.forEach(element =>
let x = element.payload.toJSON();
x["$key"] = element.key;
this.bookList.push(x as Book)
)
// SHARED DATA HERE
)
book.service.ts
import Injectable from '@angular/core';
import AngularFireDatabase, AngularFireList from 'angularfire2/database';
import Book from '../models/book'; // Model
@Injectable(
providedIn: 'root'
)
export class BookService
bookList: AngularFireList<any>;
selectedBook: Book = new Book(); // Temporally save selected Book
constructor(private firebase: AngularFireDatabase)
getBooks()
return this.bookList = this.firebase.list('books');
books.model.ts
export class Book
$key: string;
title: string;
author: string;
gender: string;
language: string;
image: string;
likes: number;
price: number;
new: boolean;
【问题讨论】:
考虑将任何过滤代码或共享列表移动到BookService
。这样,您可以从那里共享完整或过滤的列表。任何使用BookService
的组件都可以使用它们。
【参考方案1】:
在您的book.service.ts
中创建一个filterdData
变量和函数来设置filterdData
,如下所示。使用import Subject from 'rxjs';
导入Subject
filteredData = new Subject<any>();
setFilteredData(data)
this.filteredData.next(data);
然后在您的fixed-nav.component.ts
完成过滤后设置过滤数据,如下所示
this.bookService.setFilteredData(filteredData);
最后从books-grid.component.ts
订阅book.service.ts
中的filteredData
,如下所示,并将数据分配给您想要的变量。
constructor(private bookService: BookService)
bookService.filteredData.subscribe((data)=>
// Assign the data into variable that you want e.g this.filteredData = data;
)
希望对你有帮助!
【讨论】:
非常感谢,这正在工作!也想试试上面的选项,你认为它是更好的选择吗?所以我可以在任何其他组件中使用该服务 @Sergi 很高兴听到这个消息:)。是的,您也可以使用此服务的其他组件,它会正常工作 嘿我有一个问题,每次我订阅更改时,它都会堆叠,就像它订阅所有事件一样,如何实例化 Subject() 所以它只订阅一次 在你的组件上实现OnDestroy
,在ngOnDestroy()
内部取消订阅observable。例如首先声明一个subscription: ISubscription;
变量并分配this.subscription = bookService.filteredData.subscribe((data)=> )
和内部ngOnDestroy()
像这样使用this.subscription.unsubscribe();
【参考方案2】:
您可以使用另一个共享服务,在其中更新书单,然后从您的 BooksGridComponent 或任何其他需要的组件中订阅此过滤后的书单的任何更改事件。我稍微修改了你的代码。
类似这样的:
创建一个新服务,将过滤后的 BooksList 作为 Observable 返回,以便任何组件都可以订阅它
import Injectable from '@angular/core';
import Observable, Subject from 'rxjs'; // For rxjs 6
@Injectable(
providedIn: 'root'
)
export class SharedDataService
private filteredBookList: Subject<Book[]> = new Subject<Book[]>();
constructor()
public getFilteredBookList(): Observable<Book[]>
return this.filteredBookList.asObservable();
public setFilteredBookList(books: Book[]): void
this.filteredBookList.next(books);
fixed-nav.component.ts:
这里您只需调用 SharedDataService 并设置过滤后的BookList。
this.sharedDataService.setFilteredBookList(filteredData);
现在在您的 books-grid.component.ts 中:
在这里你要订阅filteredBookList的任何变化
this.sharedDataService.getFilteredBookList().subscribe((books: Book[]) =>
// Do Something with the filtered BookList from SharedDataService
)
【讨论】:
在导入 'rxjs/Rx' 时遇到问题; 没有该导入应该可以正常工作。我编辑了答案!以上是关于Angular Observable,在组件内共享数据的主要内容,如果未能解决你的问题,请参考以下文章
Angular2 中的共享服务和 Observable、BehaviourSubject
如何在 Input Angular Decorator 中使用 Observable?
Angular - 在另一个组件中使用 observable(在异步数据调用中获取值)