我正在放慢从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;
}
答案 0 :(得分:3)
在一个地方更新服务并让它更新很容易 其他地方自动。?
使用Angular模块而不是组件注册服务。
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。