Angular 6:更改我的服务时更新组件中的值

问题描述 投票:3回答:4

我的目标原则上很简单,但我不能把它放到位:我希望在更改服务变量时更新我的​​一个组件。

为了更好地解释我的问题,这里有一个例子:

在这里,我有一项服务可以增加或减少一些积分。当它接收到对其某个功能的调用时,它会减少或增加这个点数。它还说这个变量是偶数还是奇数

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TestService {
  Number: number = 0;
  IsOdd: boolean = false;

  constructor() {}

  IncreaseNumber() {
    this.Number = this.Number + 1;
    this.IsOdd = !this.IsOdd;
  }

  DecreaseNumber() {
    this.Number = this.Number - 1;
    this.IsOdd = !this.IsOdd;
  }
}

*在这里,我有我的组件,需要知道我的数字是偶数还是奇数。

初始化时没问题!它知道它!

每次数字在我的服务中更改(test.service.ts)时,我确保我的组件中的值对/导入更改(test.component.ts)?*

import { Component, OnInit } from '@angular/core';
import { TestService } from '../test.service'

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})

export class TestComponent implements OnInit {

  IsOdd: boolean = false;

  constructor(MyService: TestService) {}

  ngOnInit() {
    this.IsOdd = MyService.IsOdd;
  }

}

我该怎么办?

我的组件是否需要subscribe以某种方式提供给我的服务?或者我是否必须使用像ngOnInit这样的功能但是要更新?

提前致谢

angular typescript service components
4个回答
3
投票

如果这些服务变量属于像Object或Array这样的复杂类型,它会自动更新,因为它们是引用类型。但由于您具有类型编号和布尔值的服务变量,因此它们不会自动更新,因为它们是基本类型,因此通过值传递。

所以你必须使用BehaviorSubjects并将它们暴露给asObservables。您将通过调用BehaviorSubject方法更新这些nexts的值。这是如何做:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TestService {
  private myNumberValue = 0;
  private isOddValue = false;
  private myNumber: BehaviorSubject<number> = new BehaviorSubject<number>(this.myNumberValue);
  private isOdd: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

  myNumber$: Observable<number> = this.myNumber.asObservable();
  isOdd$:  Observable<boolean> = this.isOdd.asObservable();

  constructor() {}

  increaseNumber() {
    this.myNumberValue = this.myNumberValue + 1;
    this.myNumber.next(this.myNumberValue);
    this.isOddValue = !this.isOddValue;
    this.isOdd.next(this.isOddValue);
  }

  decreaseNumber() {
    this.myNumberValue = this.myNumberValue - 1;
    this.myNumber.next(this.myNumberValue);
    this.isOddValue = !this.isOddValue;
    this.isOdd.next(this.isOddValue);
  }
}

现在在你的组件中,你需要做的就是subscribe到服务中的publicly暴露的Observable值:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { TestService } from '../test.service'
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})

export class TestComponent implements OnInit, OnDestroy {

  isOdd: boolean;
  subscription: Subscription;

  constructor(private testService: TestService) {}

  ngOnInit() {
    this.subscription = this.testService.isOdd$.subscribe(isOdd => this.isOdd = isOdd);
  }

  ngOnDestroy() {
    this.subscription && this.subscription.unsubscribe();
  }

}

现在,因为你在subscribe中有isOdd$d到ngOnInit,它在组件初始化期间被调用,所以每次在服务中的isOdd发生变化时,你的Component上的isOddValue都会更新。

此外,由于这是一个自定义subscription,它应该被分配给组件(subscription)中的属性,该属性类型为Subscription,这是我们从subscribe方法获得的返回值。我们将不得不在unsubscribe上调用ngOnDestroy来避免内存泄漏。

PS:根据Angular's Styleguide,Angular Classes中的属性和方法名称应该在lowerCamelCase中。

使用较低的驼峰案例来命名属性和方法。


1
投票

对于你要说的工作,你应该在TestComponent中增加/减少服务中的number,而不是在其他组件中。

import { Component, OnInit } from '@angular/core';
import { TestService } from '../test.service'

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})

export class TestComponent implements OnInit {

  IsOdd: boolean = false;

  constructor(MyService: TestService) {}

  ngOnInit() {
    this.IsOdd = MyService.IsOdd;
  }

  increase() {
    MyService.IncreaseNumber();
  }

  decrease() {
    MyService.DecreaseNumber();
  }

  getIsOdd() {
    return MyService.IsOdd;
  }

}

1
投票

您可以使用多种解决方案,包括设置Observable以订阅更改。这些都是有效的解决方案。

最简单的解决方案是绑定到模板中的服务而不是值:

<div> {{ MyService.IsOdd }} </div>

ngOnInit中,您将布尔值赋给组件上的属性。该值永远不会改变。为了创建数据绑定并响应更改,您必须使用需要.的对象绑定对属性的引用。因此,MyService.IsOdd将在模板中工作。

https://stackblitz.com/edit/angular-rktij7


0
投票

可观察是一种很好的方法。

另一个简单的方法,在我看来更简单的是每当在IncreaseNumber中调用DecreaseNumberTestService方法时发出一个事件。

然后,在TestComponent的构造函数中,您可以订阅您在TestService中创建的事件,然后更新您的IsOdd字段(或您希望在组件中更新的任何其他字段)。此订阅是可能的,因为事件是observable的包装器。

像这样:首先,在您的服务中创建一个事件发射器

    import { Injectable } from '@angular/core';

    @Injectable({
      providedIn: 'root'
    })
    export class TestService {
      Number: number = 0;
      IsOdd: boolean = false;
      EmitIsOdd = new EventEmitter<any>();

      constructor() {}

      IncreaseNumber() {
        this.Number = this.Number + 1;
        this.IsOdd = !this.IsOdd;
        this.EmitIsOdd.emit();
      }

      DecreaseNumber() {
        this.Number = this.Number - 1;
        this.IsOdd = !this.IsOdd;
        this.EmitIsOdd.emit();
      }
    }

然后在Component构造函数中订阅该事件

    import { Component, OnInit } from '@angular/core';
    import { TestService } from '../test.service'

    @Component({
      selector: 'app-test',
      templateUrl: './test.component.html',
      styleUrls: ['./test.component.scss']
    })

    export class TestComponent implements OnInit {

      IsOdd: boolean = false;

      constructor(MyService: TestService) {
        this.MyService.EmitIsOdd.subscribe(
          () => {
            this.IsOdd = this.MyService.IsOdd;
          }    
        );
      }

      ngOnInit() {
        this.IsOdd = MyService.IsOdd;
      }
    }

你去,简单而有效。

© www.soinside.com 2019 - 2024. All rights reserved.