角度信号 - 使用 mutate() 与使用 forEach() 反应性

Oky*_*kyo 1 signals angular angular-signals

考虑到下面的Angular Signals示例,我对何时应该使用 Signal API(如mutate()update() )、何时使用 Array API(如forEach)足以触发反应性并更新 UI/模板感到有些困惑?这里有什么区别呢?使用的角度版本:16.0.1

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `
    {{usersList() | json}}
  `,
})
export class App {
  usersList: Signal<any> = inject(UserService).getUsersList();
  constructor() {
 
  }
}

bootstrapApplication(App);

@Injectable({
  providedIn: 'root',
})
export class UserService {
  private users = signal([
    { id: 1, name: 'Peter', country: 'USA' },
    { id: 2, name: 'Party Boy', country: 'USA' },
    { id: 3, name: 'John Connor', country: 'USA' },
  ]);

  constructor() {
      window.setTimeout(()=>{
        this.changeUsersListWithoutMutate();
      }, 3000),

      window.setTimeout(()=>{
        this.changeUsersListWithMutate();
      }, 5000)
  }

  changeUsersListWithoutMutate(){
    this.users().forEach((item) => {
      if (item.id === 1) {
        item.name = "changeListWithoutMutate";
      }
    });
  }

  changeUsersListWithMutate(){
    this.users.mutate((data) => {
      data.forEach((item) => {
        if (item.id === 1) {
          item.name = "changeListWithMutate";
        }
      });
    });
  }

  getUsersList() {
    return this.users;
  }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*ler 6

您在示例中观察到的是标准更改检测,因为您依赖于setTimeout().

setTimeout是由 修补的 API 之一zone.js,这意味着每次调用它时,Angular 都会触发更改检测周期并刷新 DOM。由于信号包裹的值已经改变(无论哪种方式),新值将出现在 DOM 中。

话虽这么说,回到信号基础知识:

在 中changeUsersListWithoutMutate,您没有更新信号,因为您正在读取其值并更改其嵌套值。信号本身无法知道它已被更新。

这就是为什么这changeUsersListWithMutate是要走的路。您明确告诉信号您正在更新其值,并且信号将触发更改检测。

如果我的回答中有不清楚的地方,请告诉我。