在不同组件中使用相同的对象数组,如果对一个对象进行任何更新,将在角度 8 中显示其他组件中的更新
Posted
技术标签:
【中文标题】在不同组件中使用相同的对象数组,如果对一个对象进行任何更新,将在角度 8 中显示其他组件中的更新【英文标题】:Use same array of objects in different components and if any update to one will show the update in other component in angular 8 【发布时间】:2021-10-22 06:29:50 【问题描述】:我在一个页面中使用了两个不同的组件,但在不同的部分。对象数组是从同一个服务调用中获取的。在一个组件中,我使用主机名和描述,但在第二个组件中,我显示了服务响应的所有值
我正在使用 contenteditable 对数据进行一些更改,并且在模糊时我正在更新对象数组中的更改。最后有一个保存按钮,用于更新组件中数据库中的所有值。
第一个组件显示用户可以删除主机的主机列表。删除主机只会将其从对象数组中删除。因此,如果从第一个组件中删除主机,我希望将更改反映在第二个组件中。 在我使用 rxjs 存储来维护状态之前,它不允许我对对象数组进行任何更改,并且给出的字段错误是只读的。
如果我对第一个组件数组进行任何更改,它是否也会更新另一个组件数组。
这是我的代码:
import Store from '@ngrx/store';
import ConfirmationDialogService from '../../../../pages/setting/confirmation-dialog/confirmation-dialog.service';
import NotifierService from 'angular-notifier';
import VulnerabilityScanService from '../../../../services/vulnerability-scan.service';
@Component(
selector: 'ngx-vuln-scan-scanned-host',
templateUrl: './vuln-scan-scanned-host.component.html',
styleUrls: ['./vuln-scan-scanned-host.component.scss'],
)
export class VulnScanScannedHostComponent implements OnInit
scannedHosts: any;
distinctHosts: any;
filter: any;
isDelete: any;
private notifier: NotifierService;
constructor(private VulnerabilityScanService: VulnerabilityScanService,
private confirmationDialogService: ConfirmationDialogService,
notifier: NotifierService,
private store: Store<any>)
this.notifier = notifier;
ngOnInit()
this.filter = JSON.parse(localStorage.getItem('reportFilters'));
this.VulnerabilityScanService.getReportDataOnHostSchedule(this.filter).subscribe(payload =>
this.scannedHosts = payload;
const key = 'ip';
const arrayUniqueByKey = [...new Map(this.scannedHosts.map(item =>
[item[key], item])).values()];
this.isDelete = arrayUniqueByKey.length;
);
removeHost(host, index)
this.confirmationDialogService.confirm('Delete HOST', 'Do you want to delete selected HOST?')
.then((confirmed) =>
if (confirmed)
this.removeHostEntries(host, this.scannedHosts);
console.log(this.scannedHosts);
this.showNotification('success', 'HOST successfully deleted.');
else
);
removeHostEntries(hostip, scannedHosts)
scannedHosts.forEach((value,index)=>
if(value.ip==hostip) scannedHosts.splice(index,1);
);
public showNotification(type: string, message: string): void
this.notifier.notify(type, message);
这里是第二个组件:
import Store from '@ngrx/store';
import VulnerabilityScanService from '../../../../services/vulnerability-scan.service';
@Component(
selector: 'ngx-vuln-scan-summary',
templateUrl: './vuln-scan-summary.component.html',
styleUrls: ['./vuln-scan-summary.component.scss'],
)
export class VulnScanSummaryComponent implements OnInit
@ViewChild('searchInput', static: false ) searchInput: ElementRef;
summaryList: any;
editedList: any;
showAlert: false;
selectedOrderBy: any = '0';
selectedFilterBy: any;
public isDetailsOpen: boolean[] = [] ;
// enableEditDesc : boolean[] = [];
// enableEditDescIndex : boolean[] = [];
constructor(private VulnerabilityScanService: VulnerabilityScanService,private store: Store<any>)
ngOnInit()
this.selectedFilterBy = JSON.parse(localStorage.getItem('reportFilters'));
this.VulnerabilityScanService.getReportDataOnHostSchedule(this.selectedFilterBy).subscribe(payload =>
this.summaryList = payload;
console.log(this.summaryList)
);
saveReport(data)
this.VulnerabilityScanService.saveReviewedReport(data).subscribe(payload =>
console.log(payload);
);
toggleRow(i: any)
this.isDetailsOpen[i] = !this.isDetailsOpen[i];
【问题讨论】:
这是通往不可维护代码的捷径。状态管理解决方案不允许出于某种原因改变数据。一个组件应使用最新更改更新状态,并且该状态也将传播到另一个组件,而无需更改数据。 之前我在做状态管理,但是如果我对页面进行任何内联编辑,它就不允许我更新数组。 你应该继续使用 rxjs 但你应该使用行为主题。 【参考方案1】:如果你不想使用状态管理,我会尝试这样的。
定义一个共享单例服务。
@Injectable( providedIn: 'root' )
export class ReportDataStore
private _data: any[];
get data()
return this._data;
set data(d)
return this._data = d;
将其注入两个组件并设置数据。
this.VulnerabilityScanService.getReportDataOnHostSchedule(this.filter).subscribe(payload =>
this.reportDataStore.data = payload;
this.scannedHosts = this.reportDataStore.data;
const key = 'ip';
const arrayUniqueByKey = [...new Map(this.scannedHosts.map(item =>
[item[key], item])).values()];
this.isDelete = arrayUniqueByKey.length;
);
this.VulnerabilityScanService.getReportDataOnHostSchedule(this.selectedFilterBy).subscribe(payload =>
this.reportDataStore.data = payload;
this.summaryList = this.reportDataStore.data;
console.log(this.summaryList)
);
组件中的局部变量现在应该保持对 ReportDataStore 服务中相同数组的引用。
【讨论】:
【参考方案2】:在这里,我使用 Observable 和 Subject 解决了这个问题。这是服务代码:
import Observable, Subject from 'rxjs';
@Injectable(providedIn: 'root')
export class VulScanConfig
private subject = new Subject<any>();
constructor()
sendReport(passedData: any)
this.subject.next(passedData);
getReport(): Observable<any>
return this.subject.asObservable();
```
Then in my parent component when any action is done I've called the sendReport function of data servicee. Here's the code of parent component:
```sendReport(data): void
this.vulScanConfig.sendReport(data);
removeHost(host, scheduleid, hostkey)
this.confirmationDialogService.confirm('Delete HOST', 'Do you want to delete selected HOST?')
.then((confirmed) =>
if (confirmed)
const assetFilterData =
scheduleId: scheduleid,
hostkey:hostkey,
host: host,
filteredData: this.filteredHosts
;
this.sendReport(assetFilterData);
);
```
The child component then subscribe to data by calling getReport function of data service and subscribe to message.
```import Subscription from 'rxjs';
constructor(private VulnerabilityScanService: VulnerabilityScanService,
private vulScanConfig: VulScanConfig,
private store: Store<any>)
this.subscription = this.vulScanConfig.getReport().subscribe(message=>
if (message)
this.summaryList = message.filteredData;
this.hostkey = message.hostkey;
this.ip = message.host;
this.scheduleId = message.scheduleId;
);
ngOnDestroy()
this.subscription.unsubscribe();
```
【讨论】:
以上是关于在不同组件中使用相同的对象数组,如果对一个对象进行任何更新,将在角度 8 中显示其他组件中的更新的主要内容,如果未能解决你的问题,请参考以下文章
Javascript/Coffeescript 在值相同时对多个键上的对象数组进行排序