什么是 Angular Composable 概念

简介: 什么是 Angular Composable 概念

image.png

我们都知道 Lodash,它是一个在项目中重用无状态逻辑的库。那么,如果在 Angular 项目中我们有一个类似的工具包来重用有状态逻辑呢?


Composables 并不是一个新的概念,它是来自 Vue.js 的一个概念。我在这篇博客中使用的许多示例和想法直接来自 Vue.js Composables 文档。


在版本 16.0.0-next.0 中,Angular 团队引入了 Signals 的实现,Signals 是一种反应性的基本组件,可以在 Angular 中提供精细的反应性能力。随着这样的重大变化,还考虑到 Angular 团队在最新版本中引入的其他非常有用的功能,比如 inject 函数或 DestroyRef 的概念,不可避免地会出现新的模式。本文试图在 Angular 的上下文中探索这个模式。


在 Angular 自身中,我们已经看到了我们可以称之为“功能型服务(Functional Services)”的过渡。它始于版本 14.2.0 中功能型守卫(functional guards)和解析器(resolvers)的引入,继续于版本 15.0.0 中功能型拦截器(functional interceptors)的引入。但是什么是 Angular Composable,为什么以及如何在项目中使用它?


什么是 Angular Composable?


在 Angular 应用程序的上下文中,一个 composable 是一个使用 Signals API 封装有状态逻辑的函数。这些可组合函数可以在多个组件中重复使用,可以相互嵌套,并且可以帮助我们将组件的有状态逻辑组织成小型、灵活和简单的单元。


与我们创建 util 函数以在组件之间重用无状态逻辑的方式相同,我们创建 composable 以共享有状态逻辑。


但是让我们看看在 Angular 应用程序中如何编写一个 composable。在下面的示例中,我没有使用 Angular Signals RFC 中提议的 API。当此 API 的所有功能就位时(例如应用程序渲染生命周期钩子,基于 Signal 的查询),我们将能够以更好的方式编写这些可组合函数,并能够为它们提供更多功能。


让我们从一个非常简单的示例开始。

Mouse Tracker Example
使用 Signals 在 Angular Component 里实现 mouse tracking 功能:
@Component({
  standalone: true,
  template: ` {{ x() }} {{ y() }} `,
})
export class MouseTrackerComponent implements AfterViewInit, OnDestroy {
  // injectables
  document = inject(DOCUMENT);
  // state encapsulated and managed by the composable
  x = signal(0);
  y = signal(0);
  ngAfterViewInit() {
    document.addEventListener('mousemove', this.update.bind(this));
  }
  // a composable can update its managed state over time.
  update(event: MouseEvent) {
    this.x.update(() => event.pageX);
    this.y.update(() => event.pageY);
  }
  ngOnDestroy() {
    document.removeEventListener('mousemove', this.update.bind(this));
  }
}


可以对其重构,增加通用性:


// mouse-tracker.ts file
export function useMouse() {
  // injectables
  const document = inject(DOCUMENT);
  // state encapsulated and managed by the composable
  const x = signal(0);
  const y = signal(0);
  // a composable can update its managed state over time.
  function update(event: MouseEvent) {
    x.update(() => event.pageX);
    y.update(() => event.pageY);
  }
  document.addEventListener('mousemove', update);
  // lifecycle to teardown side effects.
  inject(DestroyRef).onDestroy(() =>
    document.removeEventListener('mousemove', update)
  );
  // expose managed state as return value
  return { x, y };
}


其他 Component 也可以重用了:


@Component({
  standalone: true,
  template: ` {{ mouse.x() }} {{ mouse.y() }} `,
})
export class MouseTrackerComponent {
  mouse = useMouse();
}
相关文章
|
7月前
|
JavaScript API
什么是 Angular Composable 概念
什么是 Angular Composable 概念
42 0
|
7月前
|
JavaScript 前端开发
关于 Angular 编程中的 shim 概念
关于 Angular 编程中的 shim 概念
47 0
|
4天前
|
JavaScript 前端开发 架构师
Angular进阶:理解RxJS在Angular应用中的高效运用
RxJS(Reactive Extensions for JavaScript)是JavaScript的一个响应式编程库,特别适用于处理异步数据流。
10 0
|
6天前
|
API 开发者
Angular UntypedFormControl 的使用场景介绍
Angular UntypedFormControl 的使用场景介绍
12 0
|
6天前
|
开发者
Angular UntypedFormControl markAsDirty 方法的用途介绍
Angular UntypedFormControl markAsDirty 方法的用途介绍
7 0
|
6月前
|
前端开发 JavaScript 搜索推荐
什么是 Angular 应用的 re-hydration 过程
什么是 Angular 应用的 re-hydration 过程
23 1
|
7月前
|
监控 JavaScript 前端开发
Angular 应用程序的 Hydration 概念详解
Angular 应用程序的 Hydration 概念详解
35 0
|
8月前
从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来
同 Angular service 的单例特性不同,Angular 组件和指令通常会被多次实例化,比如 HTML markup 中每出现一次 Component 的 selector,就会触发 Component 的一次实例化。
44 0
|
8月前
|
存储
Angular forRoot 方法的使用场合介绍
Angular forRoot 方法的使用场合介绍
96 1
angular37-angular实现todolist基本结构
angular37-angular实现todolist基本结构
117 0
angular37-angular实现todolist基本结构