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

Angular Material Mat-Step子组件无法读取localStorage值排查

问题根因

三个核心问题导致异常:

  • 基础代码拼写/逻辑错误:Form1存储localStorage用的key是objext,Form2取值时写的key是未闭合的'obj,取值赋值给objectSave变量,判断状态时却用了未定义的armaSalva变量,逻辑本身无法正常执行。
  • 生命周期执行时机错误:<mat-step>默认在页面首次加载时就会实例化所有步骤内的子组件,constructor、ngOnInit钩子仅在初始化时执行一次。等第一步保存完数据跳转第二步时,Form2早就完成初始化,不会再重新执行初始化钩子读取新写入的存储值。
  • 事件未绑定:父组件定义的stepChanged方法没有绑定到步进器的切换事件上,步骤切换时不会触发任何自定义同步逻辑。
修复步骤

1. 统一存储逻辑,封装状态同步方法

首先修正key名、变量名的错误,把Form2读取localStorage、更新校验状态的逻辑封装成可重复调用的公共方法:
Form1Component存储逻辑修正:

// Form1Component save方法
private save(stepper: MatStepper) {
  this.dadosArmaService.save(frm).subscribe((res) => {
    // 统一存储key,避免拼写错误
    localStorage.setItem("form1Cache", JSON.stringify(res));
    stepper.next();
  }, (e) => console.error(e));
}

Form2Component新增公共同步方法,替换原来写在constructor、ngOnInit里的错误逻辑:

import { Validators } from '@angular/forms';
import { MatStepper } from '@angular/material/stepper';

export class Form2Component implements OnInit {
  @Input() stepper!: MatStepper;
  isCheck = false;
  formT = this.formBuilder.group({
    check: [false, Validators.requiredTrue]
  });

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit(): void {}

  ngAfterViewInit() {
    this.stepper._getIndicatorType = () => 'number';
  }

  // 公共同步方法,每次进入步骤时可调用
  syncStatusFromStorage() {
    const cache = localStorage.getItem('form1Cache');
    this.isCheck = cache !== null;
    const checkControl = this.formT.get('check');
    
    if (this.isCheck) {
      // 存在缓存数据时移除复选框校验
      checkControl?.clearValidators();
    } else {
      // 无缓存时要求必须勾选
      checkControl?.setValidators(Validators.requiredTrue);
    }
    // 刷新控件校验状态,避免步进器被卡住
    checkControl?.updateValueAndValidity();
  }
}

2. 绑定步进器切换事件,进入第二步时触发同步

父组件模板中给步进器绑定selectionChange事件,同时通过@ViewChild获取Form2实例,切换到第二步时主动调用同步方法:
父组件模板修正:

<mat-horizontal-stepper #stepper [linear]="true" (selectionChange)="stepChanged($event, stepper)">
  <mat-step [stepControl]="form" [optional]="isOptional">
    <ng-template matStepLabel>Form One</ng-template>
    <app-form [stepper]="stepper"></app-form>
  </mat-step>

  <mat-step [stepControl]="formT" [optional]="isOptional">
    <ng-template matStepLabel>Arma</ng-template>
    <app-formT [stepper]="stepper"></app-formT>
  </mat-step>
</mat-horizontal-stepper>

父组件逻辑修正:

import { ViewChild } from '@angular/core';
import { MatStepper } from '@angular/material/stepper';
import { Form2Component } from './form2/form2.component'; // 替换为项目实际路径

export class FirstComponent implements OnInit {
  isOptional = false;
  @ViewChild(Form2Component) form2Comp!: Form2Component;

  ngOnInit(): void {}

  stepChanged(event: any, stepper: MatStepper) {
    stepper.selected.interacted = false;
    // 切换到第二个步骤(索引从0开始,第二个为1)时同步存储状态
    if (stepper.selectedIndex === 1) {
      this.form2Comp.syncStatusFromStorage();
    }
  }
}

3. (可选优化)配置步骤懒加载

如果使用Angular Material 9及以上版本,可以给步骤配置懒加载,只有进入对应步骤时才实例化子组件,此时直接把读取存储的逻辑写在Form2的ngOnInit里即可,不需要父组件主动调用方法。模板修改方式:

<mat-step [stepControl]="formT" [optional]="isOptional">
  <ng-template matStepLabel>Arma</ng-template>
  <!-- 用matStepContent包裹,实现进入步骤才渲染组件 -->
  <ng-template matStepContent>
    <app-formT [stepper]="stepper"></app-formT>
  </ng-template>
</mat-step>

注意:懒加载模式下组件在离开步骤时会被销毁,再次进入时会重新实例化,会重复执行ngOnInit等初始化钩子,读取存储的逻辑可以直接放在初始化钩子里执行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:51:22