Angular React Vue 比较 – 注入篇

关于依赖注入,在 Angular 中依赖项主要是 Service ,它的应用场景非常广泛。在 Angular 中它是一种设计模式和机制,用于创建应用程序的某些部分并将其传递到需要它们的应用程序的其他部分。

关于 React ,它并没有提出依赖注入的概念,不过使用 Context 深层传递参数也解决了向深层组件传递数据的问题。

在 Vue 中,依赖注入的设计主要是为了解决 Prop 的逐级透传问题。

本篇三个框架的对比专注于向深层组件传递数据。

同级子组件注入数据
远亲组件注入数据

Angular

在 Angular中,最常用的注入是 Service ,下面是一个可以被注入的 Service:

// @Injectable 装饰器以表明此类可以被注入
@Injectable()
class HeroService {}

我们可以在三个级别提供依赖项,它们分别是:组件级别、NgModule 级别与应用程序根级别。

  • 在组件级别,使用 @Component 装饰器的 providers 字段。在这种情况下,HeroService 将可用于此组件的所有实例以及它的模板中使用的其他组件和指令。例如:
@Component({
  selector: 'hero-list',
  template: '...',
  providers: [HeroService]
})
class HeroListComponent {}

当你在组件级别注册提供者时,该组件的每个新实例都会获得一个新的服务实例。

  • 在 NgModule 级别,要使用 @NgModule 装饰器的 providers 字段。在这种情况下,HeroService 可用于此 NgModule 或与本模块位于同一个 ModuleInjector 的其它模块中声明的所有组件、指令和管道。当你向特定的 NgModule 注册提供者时,同一个服务实例可用于该 NgModule 中的所有组件、指令和管道。例如:
@NgModule({
  declarations: [HeroListComponent]
  providers: [HeroService]
})
class HeroListModule {}
  • 在应用程序根级别,允许将其注入应用程序中的其他类。这可以通过将 providedIn: ‘root’ 字段添加到 @Injectable 装饰器来实现:
@Injectable({
  providedIn: 'root'
})
class HeroService {}

当你在根级别提供服务时,Angular 会创建一个 HeroService 的共享实例,并将其注入到任何需要它的类中。

注入依赖项的最常见方法是在类的构造函数中声明它。例如,如果 HeroListComponent 要用 HeroService,则构造函数可以如下所示:

@Component({ … })
class HeroListComponent {
  constructor(private service: HeroService) {}
}

React

通常来说,你会通过 props 将信息从父组件传递到子组件。但是,如果你必须通过许多中间组件向下传递 props,或是在你应用中的许多组件需要相同的信息,传递 props 会变的十分冗长和不便。Context 允许父组件向其下层无论多深的任何组件提供信息,而无需通过 props 显式传递。

创建 Context

// LevelContext.js
import { createContext } from 'react';

export const LevelContext = createContext(1);

使用 Context

// Heading.js
import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';

export default function Heading({ children }) {
  const level = useContext(LevelContext);
  // ...
}

提供 Context

把要使用 context 的组件用 context provider 包裹起来以提供 LevelContext 给它们。

// Section.js
import { LevelContext } from './LevelContext.js';

export default function Section({ level, children }) {
  return (
    <section className="section">
      <LevelContext.Provider value={level}>
        {children}
      </LevelContext.Provider>
    </section>
  );
}

Vue

一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

我们可以在两个级别提供依赖项,它们分别是:组件级别与应用程序根级别。

  • 在组件级别,要为组件后代提供数据,需要使用到 provide() 函数:
<script setup>
import { provide } from 'vue'

provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
</script>
  • 在应用程序级别,提供的数据在该应用内的所有组件中都可以注入:
import { createApp } from 'vue'

const app = createApp({})

app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')

注入数据:

<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>

小结

在三大框架中, Angular 的依赖注入通常是服务,应用比较广泛,本篇文章专注于向深层组件传递数据的注入与对比。

文章参考链接:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注