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

无法从Angular服务中获取Signal值的问题求助

问题:Angular Service中Signal存储对象后获取为null

我尝试通过Service存储选中的Division对象,再在详情表单中获取该对象。设置操作时控制台能看到对象已填充,但获取时该对象却变为null。

相关代码

Division Service代码

private currentDivision = signal<Division>(new Division(), undefined);

setCurrentDivision(division: Division): void {
  this.currentDivision.set(division);
  console.log(this.currentDivision());
}
getCurrentDivision(): Division {
  console.log(this.currentDivision());
  return this.currentDivision();
}

列表组件代码

onSelect(division: Division): void {
  this._divisionService.setCurrentDivision(division);
}

详情表单组件代码

divisionService = inject(DivisionService);
constructor(private fb: UntypedFormBuilder) {
  console.log(this.divisionService.getCurrentDivision());
  this.division = this.divisionService.getCurrentDivision();
}

原因及解决方案

核心原因

  • 初始化时机不匹配:详情表单组件的constructor在组件创建时立即执行,大概率早于你在列表组件触发setCurrentDivision的时机——此时Service里的Signal还是初始的new Division(),如果你的Division默认构造生成的是空对象/null,就会出现获取到null的情况。
  • 未利用Signal的响应式特性:在constructor里仅获取一次Signal的值,不会追踪后续更新,就算之后Signal被修改,组件里的division变量也不会同步更新。

解决方法

1. 规范Signal初始化(可选)

Signal的第二个参数是配置项,无需传undefined,简化为:

private currentDivision = signal<Division>(new Division());

2. 响应式监听Signal变化

不要在constructor里一次性取值,改用computed或effect来追踪Signal的更新:

divisionService = inject(DivisionService);
// 用computed创建响应式变量,模板中直接绑定即可
division = computed(() => this.divisionService.getCurrentDivision());

// 或者用effect监听变化,用于表单赋值等逻辑
constructor(private fb: UntypedFormBuilder) {
  effect(() => {
    const currentDiv = this.divisionService.getCurrentDivision();
    console.log(currentDiv);
    this.fillForm(currentDiv);
  });
}

private fillForm(division: Division) {
  // 将数据填充到表单
  this.divisionForm.patchValue(division);
}

3. 改用路由参数传递(更可靠的方案)

依赖Service存储对象容易受页面刷新、组件销毁重建影响,建议通过路由传递Division的ID,在详情组件中重新获取数据:

// 列表组件跳转时携带ID
onSelect(division: Division): void {
  this.router.navigate(['/division/detail', division.id]);
}

// 详情组件通过路由ID获取数据
constructor(
  private fb: UntypedFormBuilder,
  private route: ActivatedRoute,
  private divisionService: DivisionService
) {
  const divId = this.route.snapshot.paramMap.get('id');
  if (divId) {
    this.divisionService.getDivisionById(divId).subscribe(division => {
      this.division = division;
      this.fillForm(division);
    });
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:40:12