Angular 5服务数据未更新

时间:2018-03-27 12:54:32

标签: angular angular5 angular-services

我正在放慢从AngularJS迁移到Angular(2+)并且偶然发现了什么。

在AngularJS中,我使用了大量工厂和服务来跨指令,控制器和其他服务共享数据。可以在一个地方轻松更新服务,并在其他任何地方自动更新服务。

但是,当我更改服务变量时,我试图在Angular 5中以类似的方式使用服务,并且“没有发生任何事情”。

我见过一些解决方案涉及创建“拉”新数据的函数或更新“Angular change service”以将事件绑定到变量的建议。

但是,我的应用程序在许多位置使用了许多变量。我必须在每个使用它们的单个组件中单独订阅每个变量,并且更改服务以针对每个变量发出更改,这似乎是不正确的。

我只是错过了什么?

谢谢! 韦恩

例如:

主页的组件。

import { Component, OnInit } from '@angular/core';
import { HomeButtonDirective } from '../home-button.directive';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

在主页上重复使用的按钮的指令:

import { Directive, Input, OnInit, HostListener } from '@angular/core';
import { InfoService } from './info.service';

@Directive({
  selector: '[appHomeButton]',
  providers: [InfoService]
})
export class HomeButtonDirective {
  @HostListener('click', ['$event']) onclick($event) {
    this.info.showHome = false;
  }
  constructor(private info: InfoService) { }

  ngOnInit() {
  }

}

应用组件。如果showHome === true:

,将显示主页
import { Component } from '@angular/core';
import { InfoService } from './info.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers: [InfoService]
})
export class AppComponent {
  title = 'Testing a service';
  showHome = true;

  constructor(private info: InfoService) {
    this.showHome = this.info.showHome; // this works...showHome becomes false per the service (see below)
  }

 }

最后,服务:

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

@Injectable()

export class InfoService {
    showHome = false;
 }

3 个答案:

答案 0 :(得分:3)

  

在一个地方更新服务并让它更新很容易   其他地方自动。?

使用Angular模块而不是组件注册服务。

  

来自Angular docs

     

Angular模块提供程序 $username = "accountname" $pwd = "accountnamePassword" $domain = "mydomain" $req = [system.Net.WebRequest]::Create($url) $req.Credentials = new NetworkCredential($username, $pwd, $domain);已注册   应用程序的根注入器。 Angular可以注入相应的   它创建的任何类中的服务。一旦创建,就是一个服务实例   为应用程序的生命而活,Angular注入了这一项服务   每个需要它的类中的实例。

总结

如果我们希望全局共享依赖项实例并在整个应用程序中共享package main import ( "fmt" ) // function that produces i.e. sends to channel func generate(ch chan int, done chan bool) { for i := 1; i <= 12; i++ { ch <- i } done <- true } // function that consumes i.e. receives from channel func print(ch chan int) { for i:= range ch { fmt.Println(i) } } func main() { done := make(chan bool) // defer close(done) ch := make(chan int) // defer close(ch) go generate(ch, done) go print(ch) <-done } ,我们会在(@NgModule.providers)上配置它

如果我们想要在组件的每个实例之间共享一个独立的依赖实例,那么我们就在组件state属性上配置它。

答案 1 :(得分:0)

根据我的经验,你说的变量可能是一个对象,你改变了它的属性值,但它本身。

你应该改变对象而不是改变他的属性。

因此,如果您想要更改服务的复杂对象,那么更好的代码如下所示:

this.oldObject = anotherObject

如有必要,将旧对象复制到新对象。

希望它有所帮助。

答案 2 :(得分:0)

从AngularJS迁移到Angular时,我有相同的观察结果。

问题

我将使用一些示例代码来描述问题。假设我们正在构建一个CommentComponent来显示评论,而数据来自名为CommentService的服务。然后我们会写下以下内容:

this.comments: Array<Comment> = this.commentsService.commments;

这在初始化期间完全正常。但是,当服务中的数据发生更改时(例如,当新注释被推送到数组时),我们将不会看到更改反映到我们的组件。这是因为上面的代码只是构造函数中的直接(一次性)赋值,这意味着没有双向绑定。

可能的解决方案

有多种解决方案可以解决上述问题。我将分享我所知道的那些,但随意扩大答案。

使用Observables

在这种情况下,我更喜欢使用BehaviorSubject,因为它会立即返回初始值或订阅时的当前值。

private comments$: BehaviorSubject<Comment> = new BehaviorSubject([]);

...并订阅您的组件中的observable或您需要更改的任何地方:

this.commentsService.subscribe(comments => this.comments = comments);

从模板引用

另一个解决方案(或解决方法)是直接从模板引用服务属性,这允许双向绑定:

<div *ngFor="let comment of commentsService.comments">
    {{ comment | json }}
</div>

更改检测策略

另一种解决方案可能是调整Change Detection Strategy