English 中文(简体)
尚未发现的17个依赖信号变化?
原标题:Angular 17 dependent signal change not detected?

我刚刚开始用“安热信号”玩.。 现在,我有一份名单,我增加了我用我的模板显示的图表。 每当我更换一页时,它就更新了同样是信号的页面国家物体。 现在,我认为,通过在过滤器人中消费人和消费国,会带来变化,但似乎没有变化。

独立的构成部分


@Component({
  selector:  app-root ,
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  template: `
  <ul>
    @for(person of filteredPersons(); track person.name) {
      <li>
        {{ person.name }} has {{ person.money }} dollars
      </li>
    }
  </ul>
  <button (click)="previousPage()">Previous Page</button>
  <button (click)="nextPage()">Next Page</button>
  <small>Page {{ pagingState().page }} of {{ totalPages() }}</small>
  `,
  styles: [],
})
export class AppComponent {

  private persons = this.personService.persons;

  filteredPersons = computed(() => {
    console.log( One of the dependents has changed :D )
    const persons = this.persons();
    const pagingState = this.pagingState();
    const amountToSkip = (pagingState.page - 1) * pagingState.pageSize;
    return persons?.slice(amountToSkip, amountToSkip + pagingState.pageSize);;
  })

  pagingState = signal({
    page: 1,
    pageSize: 5
  })

  totalPages = computed(() => Math.ceil(this.persons()?.length / this.pagingState().pageSize));

  constructor(private personService: 个人服务) {}

  nextPage(): void {
    this.pagingState.update((state) => {
      if (state.page < this.totalPages()) state.page += 1
      return { ...state}; // Cant return state directly since it wont pickup the change :(
    })
  }

  previousPage(): void {
    this.pagingState.update((state) => {
      if (state.page > 1) state.page -= 1
      return { ...state}; // Cant return state directly since it wont pickup the change :(
    })
  }
}

个人服务


  private _persons = signal<Person[]>(undefined);
  get persons() {
    return this._persons.asReadonly();
  }

  hasLoaded = computed(() => this.persons() !== undefined);

  constructor() {
    this.refresh();
  }

  getAll(): Observable<Person[]> {
    return of([
{
        name:  Alice ,
        money: 150,
      },
      {
        name:  Bob ,
        money: 280,
      },
      {
        name:  Carol ,
        money: 210,
      },
      {
        name:  David ,
        money: 320,
      },
      {
        name:  Eva ,
        money: 180,
      },
      {
        name:  Frank ,
        money: 270,
      },
      {
        name:  Grace ,
        money: 190,
      },
      {
        name:  Helen ,
        money: 230,
      },
      {
        name:  Ivan ,
        money: 260,
      },
      {
        name:  Jack ,
        money: 290,
      },
      {
        name:  Karen ,
        money: 220,
      },
      {
        name:  Leo ,
        money: 240,
      },
      {
        name:  Mia ,
        money: 200,
      },
      {
        name:  Nina ,
        money: 310,
      },
      {
        name:  Oliver ,
        money: 170,
      },
      {
        name:  Paul ,
        money: 300,
      }
    ]).pipe(delay(500))
  }

  refresh(): void {
    this._persons.set(undefined);
    this.getAll().subscribe((persons) => {
      this._persons.set(persons);
    });
  }

我完全相信,它确实会看到这一变化。 我现在要回来一份更新的版图,但这种解决办法对我是错误的。 没有人能够解释为什么发生这种情况? 如果这种行为预期会发生,它会感到确实有反感。

问题回答

在你可能发现的情况下,信号的标书在Angular 16(在开发商审查时)和Angular 17之间作了改动,后者用更新替换。

为确定物体是否改变而更新检查参考平等,因此,为了承认这一变化,你必须制作一份全新标本。 这可能是这样:

export class SignalUtil {

    // See: https://stackoverflow.com/questions/76726079/why-doesnt-angular-signals-run-my-custom-equal-check-when-using-mutate
    public static mutate<T>(
        signal: WritableSignal<T>,
        mutatorFn: (value: T) => void
    ) {
        const val = signal();
        const clone = JSON.parse(JSON.stringify(val));
        const mutated = mutatorFn(clone);
        
        signal.set(mutated)
    }
}

And this works OK, but this implementation has a few problems: this will create a lot of garbage memory, and will break if you use objects (i.e. with functions) instead of structs inside your signals.

更好的选择是将immer安装在你的项目中,这是了解如何掩饰和处理你喜欢的物体的功能性方案的工具。 更好地实施(利用一线产品)就是这样:

import {
    WritableSignal,
} from  @angular/core ;
import {
    produce
} from  immer ;

export class SignalUtil {

    // See: https://stackoverflow.com/questions/76726079/why-doesnt-angular-signals-run-my-custom-equal-check-when-using-mutate
    public static mutate<T>(
        signal: WritableSignal<T>,
        mutatorFn: (value: T) => void
    ): boolean {
        const newState = produce(signal(), (draftState: any) => {
            mutatorFn(draftState);
        });

        // this assumes that immer returns the
        // original object instance if there were no changes
        const hasChanged = signal() !== newState;

        if (hasChanged) {
            // update the signal value if we have new state
            signal.set(newState);
        }

        return hasChanged;
    }
}




相关问题
How to generate serial signal from string?

How do I send data represented by a binary string (e.g. "01011101000100111", length is variable) to an std_logic signal given either fixed delay or clock signal? I want this for a testbench so I d ...

Simple Signals - C programming and alarm function

#include <stdio.h> #include <signal.h> void ALARMhandler(int sig) { signal(SIGALRM, SIG_IGN); /* ignore this signal */ printf("Hello"); signal(SIGALRM, ...

SIGINT handling and getline

I wrote this simple program: void sig_ha(int signum) { cout<<"received SIGINT "; } int main() { string name; struct sigaction newact, old; newact.sa_handler = sig_ha; sigemptyset(&...

Explicitly calling a destructor in a signal handler

I have a destructor that performs some necessary cleanup (it kills processes). It needs to run even when SIGINT is sent to the program. My code currently looks like: typedef boost::shared_ptr<...

Basic DSP - level adjustment

I m new to DSP programming, and I m wondering how best to carry out the seemingly basic operation of level adujustment. Say I have an 8 bit number that represents the amplitude I want a signal to be ...

accept_position signal not getting called in Ruby/Gtk2

I m creating a application with panes in Ruby/Gtk. When the panes are resized, I need to do some stuff. But I cannot figure out which signal to use. I think it is accept_position - but it don t seem ...

longjmp() from signal handler

I m using the following code to try to read an input from user and timeout and exit if more than 5 seconds pass. This is accomplished through a combination of setjmp/longjmp and the SIGALRM signal. ...

热门标签