问题描述
我有2个组件(菜单和标题)和一个服务.我想做的是,当他们从菜单中选择一个项目时,菜单将文本发送到服务,服务将其发送到标题并进行更改.我已经设法将其发送到服务,但是我不知道为什么在带有Observable的标头中它不更新.
I have 2 components (Menu and Header) and one Service. What I want to do is that when they select an item from the menu, the menu sends the text to the service and the service sends it to the header and changes it. I already managed to send it to the service, but I do not know why in the header with the Observable it does not update.
服务:
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
是一次事件:
关于完整通知的最后一部分很重要,因为一旦完成(第一次执行),它将发出complete
事件,并且不再发出.您需要做的是使用Subject
或BehaviorSubject
以获得持续的事件流.
The last part about complete notification is important since once it's done (it's executed for the first time) it emits complete
event and doesn't emit anymore. What you need to do is use Subject
or BehaviorSubject
in order to get constant stream of events.
尝试这样的事情:
@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 示例,展示了此行为.
Here is stackblitz example demonstrating this behavior.
编辑:好的,我知道问题出在哪里...它在providers
数组中,您无法在header
或menu
组件中提供服务,您必须提供它在它们上方的组件中(例如app.module
或app.component
).如果您同时在这两个组件中提供服务,则您将获得该服务的不同实例,而您想要实现的目标将无法正常工作.
EDIT: Ok, I see where the problem is... It is in providers
array, you cannot provide service in header
nor menu
components, you have to provide it in component that is above them (like app.module
or app.component
). If you provide services in both of these components you will get different instance of the service and what you want to achieve will not work.
因此,在其中一个(如果另一个是第一个的子代)中或在app.module.ts
providers 数组中(请检查 stackblitz 示例)提供passVarHelper
我提供了服务,我在一个地方(app.module.ts
)和仅提供了服务(为了获得相同的实例).
Therefore, provide passVarHelper
in either one of them (if another is child of the first one) or in app.module.ts
providers array (check the stackblitz example I provided, I provided service in app.module.ts
) and only in that one place (in order to get the same instance).
嗯,Angular有一个叫做 provider scope 的东西.例如,看一下这个定义:
Hmm, Angular has something called provider scope. For example, take a look at this definition:
这意味着,当您在根级别提供服务时,无论使用DI注入到哪里,都将获得该服务的单个实例(就像在构造函数中注入它一样).
That means that when you provide service at the root level, you will get a single instance of that service wherever you inject it using DI (like when you inject it in constructor).
但是,您还可以在任何其他组件中提供服务.通过在组件中提供服务,实际上是将服务仅限制于该组件和该组件内部的组件.本质上,通过在组件中提供服务,当您将该服务注入该组件时,您将获得该服务的新实例(除非它自己提供服务,否则所有子项都将具有该实例).
But, you can also provide services in any other component. By providing a service in the component, you are actually limiting the service only to that component and components inside that component. Essentially, by providing a service in component, you will get a new instance of that service when you inject it in that component (and all its children will have that one instance, unless they themselves provide the service).
因此,该服务及其所有子级均使用该服务的单个实例,但是如果在任何子级组件中提供该服务,则该子级及其所有子级都将获得新实例.
So, single instance of the service is used for the component and all its children, but if provided in any child component, that child and all its children will get the new instance.
希望这使它更加清晰.
有趣的阅读材料:
- Official documentation
- Provider scope
这篇关于Angular Observable不能实时显示值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!