在不同组件中使用相同的对象数组,如果对一个对象进行任何更新,将在角度 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 中显示其他组件中的更新的主要内容,如果未能解决你的问题,请参考以下文章

antd+vue3 多选框的值为对象数组

Javascript/Coffeescript 在值相同时对多个键上的对象数组进行排序

如果对象数组中两个不同对象的两个键在JavaScript中相同,则通过键查找对象[重复]

JQuery使用日期对对象数组进行排序[重复]

如何在Vue中对对象数组进行排序和过滤

请问java不同类的对象怎么放在同一个数组,然后如何对这个数组进行遍历