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
相关产品推荐
相关产品推荐

