首先:抱歉我的英语不好。
我是 Angular / Signals / Zoneless 新手,我面临一个我无法弄清楚的奇怪错误。 我得到了
Writing to signals is not allowed in a
计算的or an
效果``
我有一个信号,它是一个对象数组,包括“id”属性和一些方法 我构建了一个 get() 函数,用于检查信号数组中的特定 id,如果存在,则返回对象,否则创建对象,将其添加到信号数组中,然后返回它
只要我不在模板中使用它,这个 get 方法就可以完美工作。 在模板中,我收到了我不明白的写作信号错误
为了在信号数组的对象上保留方法,我使用了 2 行技巧 (方法的需要阻止我使用扩展运算符):
this.table().push(newTest);
this.table.set(this.table().slice());
@Component({
selector: 'app-root',
standalone: true,
imports: [JsonPipe],
template: `
<pre>
Length: {{ table().length }}
{{ get(1) | json }}
<!-- {{ get(2) | json }} uncomment to see the error in console-->
</pre>
`,
})
export class App {
table = signal(<Test[]>[]);
constructor() {
this.get(1);
}
// look for the element in table and return it
// if not present, create it, add it and return it
get(id: number): Test {
let myTest = this.table().find((elem) => elem.id == id);
if (myTest != undefined) return myTest;
let newTest = new Test(id);
// the 2 next line is the only way I foound to add an object with methods in a signal array
this.table().push(newTest);
this.table.set(this.table().slice());
return newTest;
}
}
class Test {
id: number;
constructor(id: number) {
this.id = id;
}
someMethod() {
console.log(this.id);
}
}
如果我用 setInterval 延迟信号设置线,它会起作用,但我确信如果我保持这样,它会产生可怕的副作用。
如果我使用没有方法的对象,则不会出现此问题,但我非常需要它们:p。我的意思是接口而不是类
不是角度专家,但我的大胆猜测是,当信号在 HTML 中读取时,信号在内部使用
effect
来更新 HTML,因此当您使用 set
更新信号时,它会显示错误,因为信号内部不允许更新effect
。
我认为这种方法是错误的,因为你应该在
ngOnInit
或 ngAfterViewInit
上准备信号数据,而不是在 DOM 中使用的方法上准备。
因此,您可以使用单独的方法
setValue
为数组的所有元素初始化值。
constructor() {
this.setValue(1);
this.setValue(2);
}
setValue(id: number) {
let newTest = new Test(id);
// the 2 next line is the only way I foound to add an object with methods in a signal array
this.table().push(newTest);
this.table.set(this.table().slice());
}
那么在访问信号时,你总是会得到数据,因此你可以重写 get 方法。
get(id: number): Test | undefined {
let myTest = this.table().find((elem) => elem.id == id);
if (myTest != undefined) return myTest;
return undefined;
}
import { bootstrapApplication } from '@angular/platform-browser';
import {
Component,
provideExperimentalZonelessChangeDetection,
signal,
} from '@angular/core';
import { JsonPipe } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [JsonPipe],
template: `
<pre>
Length: {{ table().length }}
{{ get(1) | json }}
{{ get(2) | json }}
</pre>
`,
})
export class App {
table = signal(<Test[]>[]);
constructor() {
this.setValue(1);
this.setValue(2);
}
setValue(id: number) {
let newTest = new Test(id);
// the 2 next line is the only way I foound to add an object with methods in a signal array
this.table().push(newTest);
this.table.set(this.table().slice());
}
// look for the element in table and return it
// if not present, create it, add it and return it
get(id: number): Test | undefined {
let myTest = this.table().find((elem) => elem.id == id);
if (myTest != undefined) return myTest;
return undefined;
}
}
class Test {
id: number;
constructor(id: number) {
this.id = id;
}
someMethod() {
console.log(this.id);
}
}
bootstrapApplication(App, {
providers: [provideExperimentalZonelessChangeDetection()],
});