angular - Angular Observable 不会实时显示我的值
问题描述
我有 2 个组件(菜单和标题)和一个服务。我想要做的是,当他们从菜单中选择一个项目时,菜单将文本发送到服务,服务将其发送到标题并更改它。我已经设法将它发送到服务,但我不知道为什么在带有 Observable 的标头中它没有更新。
服务:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/from';
import { of } from 'rxjs';
@Injectable()
export class passVarHelper{
currentIndex: string;
constructor(
){
this.currentIndex = "Title";
}
getIndex(): Observable <string> {
return of(this.currentIndex);
}
changeIndex(index:string){
this.currentIndex = index;
console.log(this.currentIndex);
}
}
标题:
import { Component, OnInit } from '@angular/core';
import { passVarHelper } from 'src/app/helpers/passVar.helper';
@Component({
selector: 'app-headerpage',
templateUrl: './headerpage.component.html',
styleUrls: ['./headerpage.component.css'],
providers: [passVarHelper]
})
export class HeaderpageComponent implements OnInit {
index:string;
constructor(private _passVarHelper: passVarHelper) {
}
ngOnInit() {
this.loadIndex();
}
loadIndex(){
this._passVarHelper.getIndex().subscribe(
response => {
if(response){
console.log(response);
this.index = response;
}
},
error => {
console.log(<any>error);
}
);
}
}
菜单:
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { passVarHelper } from 'src/app/helpers/passVar.helper';
@Component({
selector: 'app-asidenavbar',
templateUrl: './asidenavbar.component.html',
styleUrls: ['./asidenavbar.component.css'],
providers: [passVarHelper]
})
export class AsidenavbarComponent implements OnInit {
constructor(private _passVarHelper: passVarHelper) {
}
ngOnInit() {
}
menuClick(){
var indexMenu = document.getElementById('menu').innerHTML;
this._passVarHelper.changeIndex(indexMenu);
}
}
标题 HTML
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">{{index}}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#">Volver</a></li>
</ol>
</div>
</div>
</div>
</div>
解决方案
Observable.of
是一次事件,根据文档:
创建一个 Observable,它发出一些您指定为参数的值,一个接一个地发出,然后发出一个完整的通知。
关于完整通知的最后一部分很重要,因为一旦完成(第一次执行)它就会发出complete
事件并且不再发出。您需要做的是使用Subject
orBehaviorSubject
来获得源源不断的事件流。
尝试这样的事情:
@Injectable()
export class PassVarHelper {
currentIndex: string;
currentIndexObs: BehaviorSubject<string>;
constructor() {
this.currentIndex = "Title";
this.currentIndexObs = new BehaviorSubject<string>(this.currentIndex);
}
changeIndex(index: string) {
this.currentIndex = index;
this.currentIndexObs.next(this.currentIndex);
}
}
然后loadIndex
方法:
loadIndex() {
this._passVarHelper.currentIndexObs.subscribe(
response => {
if (response) {
console.log(response);
this.index = response;
}
},
error => {
console.log(<any>error);
}
);
}
这是演示此行为的stackblitz示例。
编辑:好的,我知道问题出在哪里......它在providers
数组中,您不能在组件中提供服务,您必须在它们上方的组件中提供它(如或header
)。如果您在这两个组件中提供服务,您将获得不同的服务实例,而您想要实现的目标将不起作用。menu
app.module
app.component
因此,passVarHelper
在其中一个(如果另一个是第一个的孩子)或app.module.ts
providers数组中提供(检查我提供的stackblitz示例,我在 中提供了服务app.module.ts
)并且仅在那个地方提供(为了获得相同的实例) .
嗯,Angular 有一个叫做provider scope的东西。例如,看一下这个定义:
当您在根级别提供服务时,Angular 会创建一个共享的服务实例并注入到任何需要它的类中。
这意味着当您在根级别提供服务时,无论您使用 DI 注入它(例如在构造函数中注入它时),您都将获得该服务的单个实例。
但是,您也可以在任何其他组件中提供服务。通过在组件中提供服务,您实际上将服务仅限于该组件和该组件内的组件。本质上,通过在组件中提供服务,当您将其注入该组件时,您将获得该服务的一个新实例(并且它的所有子代都将拥有该实例,除非它们自己提供该服务)。
因此,服务的单个实例用于组件及其所有子组件,但如果在任何子组件中提供,则该子组件及其所有子组件将获得新实例。
希望这使它更清楚一点。
有趣的阅读材料:
推荐阅读
- javascript - 如何在网格布局中定位最底部的容器
- go - github.com/jinzhu/gorm 和 gorm.io/gorm 有什么区别?
- typescript - 做什么
TS 中的泛型类型均值 - javascript - JavaScript 数组被覆盖
- java - 如何为 Spring Boot 编写 Junit 测试用例:
- python - 无法重定向到注册页面
- php - 如何对齐
如果文本之前的长度不同,则元素内联 - php - 在不知道最后修改时间戳的情况下同步数据
- typo3 - TYPO3 GeneralUtility Class 0; 未找到(自己的通用扩展)
- typescript - Prisma 多对多关系:创建和连接