4

引言

一 signal

是什么???

What are signals?
A signal is a wrapper around a value that notifies interested consumers when that value changes. Signals can contain any value, from primitives to complex data structures.
You read a signal's value by calling its getter function, which allows Angular to track where the signal is used.
Signals may be either writable or read-only.

译:信号是一个值的包装器,当该值发生变化时通知感兴趣的消费者。信号可以包含任何值,从原语到复杂的数据结构。
由上可知:

  1. signal 有两种类型, 一种是可写的WritableSignal,可改变值,一种是可读的Signal,不可改变值。
  2. 被signal 包装的值, 那个值的类型不受限制。
  3. 3 是属于订阅者模式,当值发生变化会通知消费者。

signal信号

可写的信号

import {Component, effect, OnInit, signal, WritableSignal} from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet],
  templateUrl: `
                <p>The count is: {{ count() }}</p>
                <button (click)="increment()">Increment</button>
               `,
  styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
  // 创建 signal()
   count: WritableSignal<number> = signal(0);

  ngOnInit(): void {
    // 改变值 .set()
    this.count.set(100);
    console.log(`The current count is: ${this.count()}`);
  }

  increment() {
    // 使用该.update()操作根据前一个值计算出一个新值:
    this.count.update(v => v + 1);
  }

  // 订阅
  effect = effect(() => {
    // 值每变化一次,执行一次
    // 可在此处作一些逻辑判断
    console.log(`effect: ${this.count()}`);
  });
}

Kapture 2024-12-05 at 11.40.36.gif

计算信号(只可读的信号)

计算信号其值来自其他信号。可以使用computed函数定义计算信号并指定派生函数。 doubleCount依赖于count()。

const count: WritableSignal<number> = signal(0);
const doubleCount: Signal<number> = computed(() => count() * 2);

计算信号的依赖性是动态的,可有可无。

const showCount = signal(false);
const count = signal(0);
const conditionalCount = computed(() => {
  if (showCount()) {
    return `The count is ${count()}.`;
  } else {
    return 'Nothing to see here!';
  }
});

signal 和 RxJS 的区别是什么?

特点SignalRxJS
关注点组件内部状态异步数据流
复杂度相对简单功能强大,但学习曲线陡峭
性能通常性能更好,尤其是在频繁更新的场景下性能取决于使用的操作符和数据量
适用场景组件内部状态管理,简单的异步操作复杂的异步操作,构建数据流应用程序

如何在组件销毁时取消 effect 的订阅?

effect()返回的是一个EffecrRef类型的对象,可调用.destory()方法对其进行销毁。
image.png

二 component 组件

impotrs

组件不再强制依赖 NgModule,可以独立存在。
在组件@Component 装饰器中有imponts, 可导入组件,指令,管道,模块。这是使用angular 19 版本生成的组件默认standalone为true, 以前是standalone默认为false。
image.png
如果设置standalone为false,组件仍然依赖 NgModule
image.png

selector 选择器

Angular 指令注解的属性解释 看这篇文章就够了。

Routing 路由

angular 创建新项目后会自动创建两个文件 app.config.ts 和app.routers.ts, 可配置使用路由

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import {provideRouter, Routes} from '@angular/router';
import {FirstComponent} from './first/first.component';
import {ViewComponent} from './view/view.component';

const routes: Routes = [
  {
    path: 'first',
    component: FirstComponent, 
    children: [
      {
        path: ':id', 
        component: ViewComponent, 
      },
    ],
  },
  {
    path: 'second',
    loadComponent: () => import('./second/second.component').then(m => m.SecondComponent),
  }
];

export const appConfig: ApplicationConfig = {
  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
};

RouterLink

routerLink 可接收数组, /path是路径,剩下的分别是参数

<a [routerLink]="['/path', param1, param2, ...]">链接文本</a>

三 设置HttpClient

不再是以前那样导入HttpClientMoudule。有是由provideHttpClient(),提供。

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(),
  ]
};

总结

1 有异步操作的话,可考虑使用signal, 可学习一下结合使用signal和RxJS
2 组件单独化了,不用写export了。
3 以前的模块,HttpClientModule, RouterModule等,改为provideHttpClient(),provideRouter(routes)形式。

参考文献

angular官方文档


吴季分
400 声望13 粉丝