在 Angular 18 中使用信号序列化模型

问题描述 投票:0回答:1

我正在尝试将模型对象序列化到本地存储(或 IndexedDB),但它包含信号。

// An example of the model I'm dealing with
export class ExampleModel {
    canSerialise = "";
    cantSerialise = signal("");
}

// What I'd like to be able to do
let exampleModel = new ExampleModel();
localStorage.setItem("example", JSON.stringify(exampleModel));

但是这不会序列化

cantSerialise
,因为信号在技术上是函数。我想避免为所有只有信号的模型手动编写序列化函数。

  • 尝试使用
    JSON.stringify()
    进行简单的序列化:
    • 期望的结果:
      '{"canSerialise":"","cantSerialise":X}'
      ,其中
      X
      可以是任何东西,只要它序列化回原始值作为信号(在本例中为
      signal("")
    • 结果(正如我担心/预期的那样)
      '{"canSerialise":""}'
  • 考虑过使用 IndexedDB,但它也无法序列化信号,因为结构化克隆算法具有与 nog 序列化函数相同的限制。
angular serialization signals angular-signals angular18
1个回答
0
投票

这不是完美的代码,但您可以编写一个自定义

toString
方法,在写入对象之前执行信号。然后我们可以调用
JSON.stringify
将仅包含值的对象转换为字符串。

请忽略我的打字错误,因为这是我能做的最好的事情,它可能看起来很难看,但它完成了工作。

export class ToStringConverter {
  toString() {
    let output: any = {};
    const that: ToStringConverter = this as never as ToStringConverter;
    for (let key in that) {
      if (that!.hasOwnProperty(key)) {
        const lookupKey: keyof ToStringConverter =
          key as keyof ToStringConverter;
        if ((that[lookupKey] as any) instanceof Function) {
          output[lookupKey] = (that[lookupKey] as Function)() as any;
        } else {
          output[lookupKey] = that[lookupKey];
        }
      }
    }
    return JSON.stringify(output);
  }
}

完整代码:

import { Component, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

export class ToStringConverter {
  toString() {
    let output: any = {};
    const that: ToStringConverter = this as never as ToStringConverter;
    for (let key in that) {
      if (that!.hasOwnProperty(key)) {
        const lookupKey: keyof ToStringConverter =
          key as keyof ToStringConverter;
        if ((that[lookupKey] as any) instanceof Function) {
          output[lookupKey] = (that[lookupKey] as Function)() as any;
        } else {
          output[lookupKey] = that[lookupKey];
        }
      }
    }
    return JSON.stringify(output);
  }
}

// An example of the model I'm dealing with
export class ExampleModel extends ToStringConverter {
  canSerialise = '';
  cantSerialise = signal('');

  constructor(canSerialize = '', cantSerialize = '') {
    super();
    this.canSerialise = canSerialize;
    this.cantSerialise = signal(cantSerialize);
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <h1>Hello from {{ name }}!</h1>
    <a target="_blank" href="https://angular.dev/overview">
      Learn more about Angular
    </a>
  `,
})
export class App {
  name = 'Angular';

  ngOnInit() {
    // What I'd like to be able to do
    let exampleModel = new ExampleModel('working', 'also working');
    localStorage.setItem('example', exampleModel.toString());
  }
}

bootstrapApplication(App);

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.