在 Angular 9 中,如何在不重新实例化的情况下更新组件的数据字段以显示在 DOM 中?



我对 Angular 9 相当陌生。我有一个程序,用户在其中输入一个名称 - 提交后 - 发送 POST HTTP 请求并存储名称。然后,我有一个不相关的子标题组件,该组件列出了使用 ngOnInit(( 使用 GET HTTP 请求存储的名称。但是,我需要子标题在每次输入新列表时动态更新该名称列表,而不仅仅是在组件实例化时。

我不确定如何进行。我敢肯定我可以简单地添加一个按钮来获取和更新所述列表,但尝试更动态的东西。提前感谢!

//SERVICE.TS...
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { NewList } from './new-list.model';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ListService {
createdLists: NewList[] = [];
constructor(private http: HttpClient) { }
createList(postData) {
return this.http
.post(
'API_KEY',
postData
);
}
getLists() {
return this.http
.get<NewList>(
'API_KEY'
).pipe(map(responseData => {
const responseArray: NewList[] = [];
for (const key in responseData) {
responseArray.push(responseData[key])
}
return responseArray;
})
);
}
}


// NEW-LIST-MENU.TS (USER ENTERS A NAME)...
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { UIService } from 'src/app/shared/ui.service';
@Component({
selector: 'app-new-list-menu',
templateUrl: './new-list-menu.component.html',
styleUrls: ['./new-list-menu.component.css']
})
export class NewListMenuComponent implements OnInit {

constructor(private listService: ListService,
private uiService: UIService,
private router: Router) { }
ngOnInit(): void {
}
onSubmit(form: NgForm) {
const listName = form.value.listname;
const newListObj = new NewList(listName, []);

this.listService.createList(newListObj)
.subscribe(() => {
this.router.navigate(['']);
});
const lists = this.listService.updateLists(newListObj);


form.reset();
}
onCancel() {
this.router.navigate(['']);
}
}


// SUB-HEADER.TS...
import { Component, OnInit, Output } from '@angular/core';
import { Router } from '@angular/router';
import { ListService } from 'src/app/shared/list.service';
import { NewList } from 'src/app/shared/new-list.model';
import { faWindowClose } from '@fortawesome/free-solid-svg-icons';
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
import { faList } from '@fortawesome/free-solid-svg-icons';
import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons';
import { Subject } from 'rxjs';

@Component({
selector: 'app-sub-header',
templateUrl: './sub-header.component.html',
styleUrls: ['./sub-header.component.css']
})
export class SubHeaderComponent implements OnInit {
createdLists: NewList[];
faWindowClose = faWindowClose;
faPlusCircle = faPlusCircle;
faList = faList;
faSignOutAlt = faSignOutAlt;
@Output() closeSub = new Subject();
constructor(private listService: ListService, 
private router: Router) { }
ngOnInit(): void {
this.listService.getLists().subscribe((responseData) => {
this.createdLists = responseData;
});
}
onCloseSelect() {
this.closeSub.next();
}
onNewListSelect() {
this.onCloseSelect();
this.router.navigate(['new-list-menu']);
}
onLogOutSelect() {
}
}```

您可以通过多种方式实现此目的,因为这些组件彼此不相关,因此可以引入状态服务并使用可观察量。 请参阅以下可能的解决方案

  1. 创建新的状态服务 列表状态服务

    export class ListStateService {
    private listData = new BehaviorSubject<NewList >({} as NewList);       
    listData$ = this.listData .asObservable();
    }
    
  2. 将 ListStateService 注入 NewListMenuComponent

在提交中,更新后,

const lists = this.listService.updateLists(newListObj);
this.listData .next(lists );
  1. 将 ListStateService 注入 SubHeaderComponent 在 ngOnInit(( 中,订阅 ListStateService.listData$,在这里您将获得更改的值

在您的服务中,使用事件发射器(非常有用(:

import { EventEmitter } from "@angular/core";
@Output() myEvent: EventEmitter<any> = new EventEmitter();

然后通过服务向子标头组件发出新数据,如下所示:

emitEvent (newData: Array<string>) {
this.myEvent.emit({
data: newData,
});
}

订阅子标题组件中的新数据ngOnInit并使用它:

this.myService.myEvent.subscribe((newData: Array<string>) => {
console.log(JSON.stringify(newData.data));
});

注意:如果在组件中不断重新订阅,订阅将导致内存泄漏,因此您可以在ngOnDestroy回调中保存订阅并调用unsubscribe()

目前还不清楚您要做什么,但是如果您尝试将数据从父组件传递到子组件,则可以使用输入字段或ViewChild执行此操作

要使用输入字段,您的父级可能如下所示:

<app-sub-header [names]="names"></app-sub-header>

然后在子项中使用"输入"字段。更新父级中的名称应实时更新子项中的相同命名变量。

最新更新