当我需要在Angular项目中使用组件之间的一些数据时,我遇到了问题.我读到使用共享数据服务是一个很好的 Select ,所以我试图实现它,但我不能.

在项目开始时,我从http请求中获取了一些类别. 这些类别需要在项目的标题和正文中使用. 所以我在app.component.ts中获取分类

constructor(
    public _categoryService: CategoryService,
    private _dataService: DataService
  ){
    this.getCategories();
  }

  getCategories(){
    this._categoryService.getCategories().subscribe(
      response => {
        if(response.status == 'success'){
          this.categories = response.categories;
          this._dataService.setCategories(this.categories);

          let categories = this._dataService.getCategories();
          console.log(categories);
        }
      },
      error => {
        console.log(<any>error);
      }
    );
  }

app.component.html

    <app-header [categories]="categories"></app-header>
 
    <!-- CONTENT -->
    <router-outlet></router-outlet>
  
    <app-footer></app-footer>
   

在标题中,我列出的类别没有问题.但我想在分类页面组件中列出它们. 我不能在中添加类别,这就是为什么我使用_dataService.

但当我点击类别路由链接

// ROUTES DEFINITIONS
const appRoutes: Routes = [
    { path: '', component: PageHomeComponent },
    { path: 'categories', component: PageCategoriesComponent },
];

我无法获取PageCategoriesComponent中的类别

constructor(
    private _dataService: DataService
  ) { }

  ngOnInit() {
    let categories = this._dataService.getCategories();
    console.log(categories);
  }

在Chrome控制台中,我看到了第一个console.log是page—categories—component的值,第二个console.log是app.component的值,所有类别的值.

拜托,有人能解释一下发生了什么吗?

EDIT 我在page—categories.component.html中添加了一个按钮,以确保app.component中的请求已经完成,类别已经加载到dataService中,但它仍然返回一个空数组

<button (click)="clickButton()">get categories</button>

Page-categories.component.ts

clickButton(){
    this._dataService.getCategories().subscribe((data) => {
      this.categories = data;
      console.log(this.categories);
    });
  }

SOLUTION 我在DataService中添加了这个:

@Injectable({
    providedIn: 'root',
})
export class DataService {
  private bSubject = new BehaviorSubject([]);

    getCategories() {
        return this.bSubject.asObservable();
    }

    setCategories(value: any) {
        return this.bSubject.next(value);
    }
}

我还从组件的提供程序中删除了DataService

@Component({
  selector: 'app-page-categories',
  templateUrl: './page-categories.component.html',
  styleUrl: './page-categories.component.css',
  providers: []
})

推荐答案

最新情况:

确保您已提供:在服务中设置"root",并确保您没有将服务添加到任何provider数组中,这将导致添加一个单独的实例,关键是所有组件共享同一个实例导出类test {}—definition,new test()—instance of class(这需要是单例!)>>


get类别是一个异步方法getCategories,因为第一个console.log在console.log给你的值的subscribe内部,但异步表示代码的其余部分都会执行,而不管subscribe是否完成.所以我推荐两种解决方案

  1. 虽然你在console.log时看到的是null,但如果你在控制台日志(log)中展开数组,你会看到这些值实际上存在(如果你在获得这些值时没有创建新数组),所以你可以访问其他值,而不需要做任何事情,你可以在*ngFor{{categories | json}}中运行数组并判断这些值是否存在.try this.categories = this._dataService.getCategories();,因为我们需要将变量存储在class属性上,以便它在html上可见.

  2. 你可以使用一个行为主体,它将保存最后一个发出的值,我们可以订阅最新的值.

服务

export class DataService {
    private bSubject = new BehaviourSubject([]);

    getCategories() {
        return this.bSubject.asObservable();
    }

    setCategories(value: any) {
        return this.bSubject.next(value);
    }
    ...

组件

...
categories: any =[];

ngOnInit() {
    this._dataService.getCategories().subscribe((data) => {
        this.categories = data;
        console.log(categories);
    });
}
...

Angular相关问答推荐

angular:从模板中的可观察数组获取随机元素

使用注入的主机组件进行指令测试

Angular :将动态创建的零部件附加为目标元素的子项

CDK虚拟滚动由于组件具有注入属性而在滚动时看到错误的值

天使17中的倒计时器

所有返回缺少权限或权限不足的FireBase项目.

VS代码中带Angular 17的缩进新控制流

Angular 16:信号更新未能更新视图

Angular,数据显示在控制台但不在应用程序中

Angular 等待对话框未显示

Angular:为什么在我的自定义 ErrorHandler 中订阅主题不触发?

angular 13 ng 构建库失败(ivy部分编译模式)

ngx-bootstrap modal:如何从模态中获取返回值?

错误:formControlName 必须与父 formGroup 指令一起使用.您需要添加一个 formGroup 指令

Angular url加号转换为空格

visibility:hidden

如何在 Angular2 中的所有请求的请求标头中发送Cookie?

实现自定义 NgbDateParserFormatter 来更改 NgbInputDatepicker 上输入值的格式是否正确?

如何为 Angular 2 中的渲染元素绑定事件监听器?

如何在 Angular 2 的同一个组件中使用多个 ng-content?