You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中Mat-Dialog临时数据存储方案咨询(替代内存存储)

Angular FormArray 临时数据存储方案(除内存外)

问题背景

我正在开发一个Angular对话框组件,用于填充FormArray——根据用户指定的qtyReceived值生成对应行数的序列号输入框。现在需要解决的是:如何临时保存用户已填写的数据?除了内存存储外,还有哪些可行的替代方案?

现有代码实现

组件初始化逻辑

ngOnInit(): void {
    this.serialForm = this.fb.group({
      id: [0],
      deliveryReceiptDetailsId:[0],
      itemCode:['', Validators.required],
      qtyReceived:[0, Validators.required],
      inputs: this.fb.array([this.CreateArray()]),
    });
    this.serialForm.get('qtyReceived').valueChanges.subscribe((res) => {
      for (let i = this.displayArray.length; i < res; i++) {
        this.displayArray.push(this.CreateArray());
        console.log(this.displayArray);
      }
    });
    this.serialForm.get('id').setValue(this.data.id),
    this.serialForm.get('qtyReceived').setValue(this.data.qtyReceived),
    this.serialForm.get('itemCode').setValue(this.data.propertyNo)
  

  }

  get displayArray():FormArray{
    return this.serialForm.get('inputs') as FormArray;
  }
  CreateArray():FormGroup{
    return new FormGroup({
      serialNum: new FormControl('', {validators: [Validators.required]}),
    });
  }

内存存储服务

@Injectable({
  providedIn: 'root'
})
export class SerialCodeService {
  private url = 'api/serial';
  private headers = new HttpHeaders({ 'Content-Type': 'application/json' });
  constructor(private http: HttpClient) { }

  getHeroes (data:any): Observable<any> {
    return this.http.post(this.url, data);
}
  }

InMemoryDataService 示例数据

@Injectable({
  providedIn: 'root'
})
export class InMemoryDataService implements InMemoryDbService {

  createDb() {
    const serial = [
      
      {id: 1, deliveryReceiptDetailsId: 0, itemCode:'sample1', qtyReceived:0 ,serialNum:"" },
      {id: 2, deliveryReceiptDetailsId: 0, itemCode:'sample2', qtyReceived:0 ,serialNum:"" },
      {id: 3, deliveryReceiptDetailsId: 0, itemCode:'sample3', qtyReceived:0  ,serialNum:""},
    ];
    return {serial};
  }
  genId(SerialBarCode: SerialCodeDTO[]): number{
    return SerialBarCode.length > 0
    ? Math.max(...SerialBarCode.map(serial => serial.id)) + 1
    : 1;
  }
}

替代存储方案

1. 浏览器本地存储(LocalStorage/SessionStorage)

这是前端最常用的临时存储方案,实现简单:

  • LocalStorage:数据持久化存储,除非用户手动清除或代码删除;
  • SessionStorage:数据仅在当前浏览器会话有效,关闭标签页后自动清空。

实现思路:监听表单值变化,将Form的value序列化为JSON字符串存入存储;组件初始化时读取并恢复表单状态。

修改组件代码示例:

ngOnInit(): void {
    // 初始化表单
    this.serialForm = this.fb.group({
      id: [0],
      deliveryReceiptDetailsId:[0],
      itemCode:['', Validators.required],
      qtyReceived:[0, Validators.required],
      inputs: this.fb.array([this.CreateArray()]),
    });

    // 从LocalStorage恢复数据
    const savedForm = localStorage.getItem('serialFormTempData');
    if (savedForm) {
      this.serialForm.setValue(JSON.parse(savedForm));
    }

    // 监听表单变化,实时保存到LocalStorage
    this.serialForm.valueChanges.subscribe(formValue => {
      localStorage.setItem('serialFormTempData', JSON.stringify(formValue));
    });

    // 原有数量变化逻辑(补充减少数量时的处理)
    this.serialForm.get('qtyReceived')?.valueChanges.subscribe((res) => {
      const currentLength = this.displayArray.length;
      if (res > currentLength) {
        for (let i = currentLength; i < res; i++) {
          this.displayArray.push(this.CreateArray());
        }
      } else if (res < currentLength) {
        // 数量减少时移除多余的输入行
        while (this.displayArray.length > res) {
          this.displayArray.removeAt(this.displayArray.length - 1);
        }
      }
    });

    // 初始化传入数据
    this.serialForm.get('id')?.setValue(this.data.id);
    this.serialForm.get('qtyReceived')?.setValue(this.data.qtyReceived);
    this.serialForm.get('itemCode')?.setValue(this.data.propertyNo);
  }

2. IndexedDB

适合存储大量、结构化的临时数据,支持事务和索引,容量远大于LocalStorage(通常50MB以上),支持离线操作。

实现思路:可以使用Angular封装的库(如dexie-angular)简化操作,将表单数据存入IndexedDB;组件初始化时查询并恢复表单状态。

核心优势:处理复杂数据结构更灵活,适合需要离线保存大量数据的场景。

3. 后端会话级临时存储

如果需要跨设备同步临时数据,或数据需要和后端交互,可以将临时数据提交到后端的会话存储(如Redis)。

实现思路:

  1. 后端提供临时数据的保存/读取接口,通过用户会话(Token/Cookie)关联数据;
  2. 前端在表单变化时调用接口保存数据;
  3. 组件初始化时调用接口拉取会话内的临时数据。

修改SerialCodeService示例:

@Injectable({ providedIn: 'root' })
export class SerialCodeService {
  private url = 'api/serial/temp';
  private headers = new HttpHeaders({ 'Content-Type': 'application/json' });

  constructor(private http: HttpClient) { }

  // 保存临时数据
  saveTempData(data: any): Observable<any> {
    return this.http.post(`${this.url}/save`, data, { headers: this.headers });
  }

  // 获取临时数据
  getTempData(): Observable<any> {
    return this.http.get(`${this.url}/get`, { headers: this.headers });
  }
}

组件中使用示例:

ngOnInit(): void {
    // ... 表单初始化逻辑

    // 拉取后端临时数据
    this.serialCodeService.getTempData().subscribe(savedData => {
      if (savedData) {
        this.serialForm.setValue(savedData);
      }
    });

    // 表单变化时保存到后端
    this.serialForm.valueChanges.subscribe(formValue => {
      this.serialCodeService.saveTempData(formValue).subscribe();
    });

    // ... 原有数量变化和数据初始化逻辑
  }

4. Cookie存储

适合小体积临时数据(最大4KB),数据会随HTTP请求自动发送到后端,适合需要和后端共享的场景。

实现示例:

// 保存到Cookie(设置1小时过期)
const formValueStr = encodeURIComponent(JSON.stringify(formValue));
document.cookie = `serialFormTemp=${formValueStr}; path=/; max-age=3600; SameSite=Lax`;

// 读取Cookie
const cookieEntry = document.cookie.split('; ').find(row => row.startsWith('serialFormTemp='));
if (cookieEntry) {
  const savedFormStr = decodeURIComponent(cookieEntry.split('=')[1]);
  const savedForm = JSON.parse(savedFormStr);
  this.serialForm.setValue(savedForm);
}

内容的提问来源于stack exchange,提问作者Yan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 11:30:51