【问题标题】:Handling a boolean field in component and service class - Angular 2处理组件和服务类中的布尔字段 - Angular 2
【发布时间】:2019-02-11 15:10:52
【问题描述】:

您好,我基本上是 Angular 的新手,在这里我试图从服务中访问一个布尔变量。我已经在服务中声明了一个值为 true 的布尔变量。基于一些逻辑,我将把该服务变量更改为 false。我在几个组件中使用的那个特定变量。 所以我面临的问题是,我分配的初始值是真实的,它会出现在我使用过的所有组件中,但是在更改了未反映在所有组件中的值之后。 像这样的服务类:

@Injectable()
export class MyService { 
running: boolean = true;
}

组件 1:

export class FirstComponent {
  constructor(private myService: MyService) { }
  check(){
  this.myservice.running = false;
  }
}

组件 2:

export class SecondComponent implements OnChanges {
      running;
      constructor(private myService: MyService) { }
      ngOnChanges(){
      this.running = this.myService.running;
      console.log('running', this.running);
      }
    }

这就是我将如何更改布尔值并从不同组件中的服务访问。我不确定这是否正确,请纠正我。

【问题讨论】:

  • 您是否在应用程序的根模块中添加了该服务?如果没有,那么它们就不会在组件之间共享。
  • 您是否尝试过在根模块中提供服务?我知道 Angular 会以这种方式创建一个可以在所有组件之间共享的服务的单例实例。我想知道您是否刚刚启动了一项新服务,而他们没有监控相同的状态
  • 如果您需要该服务是单例的,那么您应该在 approotmodule 中添加您的服务。那么只有它会充当单例,否则将为每个组件创建不同的实例
  • @anuraagdjain 是的,我已经在根模块中添加了,我可以获得初始布尔值,但是在更改后它没有得到反映..可能会有一些不同的过程进行更改会反映在组件中的访问时间
  • 必须有相同的方式来通知数据发生了变化,否则其他组件不会知道。您可以为此使用Subject。在此处阅读更多信息blog.angularindepth.com/…

标签: angular


【解决方案1】:

一个简单的答案怎么样:

1) 如果您使用的是 Angular v6 或更新版本,那么只需将您的服务更改为以下内容:

@Injectable(providedIn: 'root')
export class MyService { 
   running: boolean = true;
}

2) 搜索您的系统并确保MyService 服务列在任何模块或组件的providers 数组中。

3) 更改您的组件以使用 getter。正如其他人所说,ngOnChanges 仅适用于 @Input 属性。

  export class SecondComponent {
      running;
      constructor(private myService: MyService) { }

      get running(): boolean {
        return this.myService.running;
      }
    }

应该这样做!

当服务中的值发生变化时,Angular 的内置变化检测会拾取变化并重新获取值,调用 getter 并将更新后的值提供给模板。

您确实需要SubjectBehaviorSubject 来完成这样简单的事情。 (那些是waaaay过度使用恕我直言。)

我有一个非常简单(和类似)的例子:https://stackblitz.com/edit/angular-simpleservice-deborahk

它使用字符串,但对于布尔值的工作方式完全相同。

【讨论】:

  • 其他地方是否需要使用set或者服务可以简单地使用this.running = true来广播?
【解决方案2】:

您可以在服务中使用BehaviorSubject。然后创建一个 ObservableasObservable 的主题方法,然后在您想要的任何组件中订阅该 observable。

请注意,ngOnChanges 已更改为 ngOnInit

服务中:

private runningSubject: BehaviorSubject<boolean> = new BehaviorSubject(true);
running = this.runningSubject.asObservable();

setRunning = (value: boolean) => {
   this.runningSubject.next(value);
}

在第一个组件中:

export class FirstComponent {
  constructor(private myService: MyService) { }
  check(){
      this.myservice.setRunning(false);
  }
}

第二个组件:

export class SecondComponent implements OnInit {
      running;
      constructor(private myService: MyService) { }

      ngOnInit(){
         this.myService.running.subscribe((isRunning) => {
            this.running = isRunning;
             console.log('running', this.running);
         });

      }
}

【讨论】:

    【解决方案3】:

    首先,您必须确保您的服务是单例的,或者至少在您要连接的每个组件的范围内只有一个实例。实现此目的的最简单方法是在 AppModule 内注册您的服务 providers 别无他处

    第二件事是即使你的服务改变了它的价值,ngOnChanges 也不会被无故调用。它需要由变更检测器调用,但服务不会以您尝试使用它的方式运行变更检测。

    您应该与Observable 共享此值。

    export class TestService {
        private readonly _messageSubject: Subject<boolean>;
    
        get observable(): Observable<boolean> {
            return this._messageSubject.asObservable();
        }
    
        constructor() {
            this._messageSubject = new Subject<boolean>();
        }
    
        sendMessage(value: boolean): void {
            this._messageSubject.next(value);
        }
    }
    

    现在,注入TestService 的每个组件都可以访问两种方法:

    observable 是吸气剂。它从您的服务的主题中返回 observable。 sendMessage(value: boolean) 它将您的布尔消息发送给_messageSubject 的每个订阅者。

    如果您想订阅该主题(并访问服务价值的每一次变化),您需要以这种方式使用您的服务:

    TestService.observable.subscribe(value =&gt; { /* You can access your boolean value here with name "value" */});

    注意Subject 共享值的变化,所以subscribe 方法内的回调只会在该值的每次下一次更改后执行(这意味着它将在每次sendMessage(value: boolean) 方法的下一次调用后调用)。如果您想访问以前的值(这意味着调用 subscribe 之前的最新值)请改用 BehaviorSubject

    【讨论】:

    • 强调singleton 非常重要。因此我投了赞成票。这应该是公认的答案。
    • 在大多数情况下使用主题是多余的,尤其是像这样简单的情况。
    猜你喜欢
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多