如何更新依赖注入令牌值
How to update dependency injection token value
Angular 依赖项注入让您可以使用令牌而不是服务来注入字符串、函数或对象 class。
我在我的模块中这样声明它:
providers: [{ provide: MyValueToken, useValue: 'my title value'}]
我是这样使用它的:
constructor(@Inject(MyValueToken) my_value: string) {
this.title = my_value;
}
但是,如何更新组件的值并让其他组件每次都获取新值?换句话说,我想模拟使用 BehaviorSubject
之类的东西来发出和接收值的功能。
如果这不可能,那么如果它们仅提供静态数据,那么这些注入标记值的用途是什么,因为我可以简单地在我的组件中声明静态值并直接使用它。
您可以使用 BehaviorSubject
而不是不可变的原语,然后在一个组件中访问和更新它并在另一个组件中订阅:
providers: [{ provide: MyValueToken, useValue: new BehaviorSubject('')}]
// consumer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.subscribe((my_value)=>this.title = my_value);
}
// producer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.next('my title value');
}
除了精灵:
如果您有一个用例,其中每个消费者都需要自己的 BehaviourSubject 实例。 (我碰巧在这个用例中)。确保定义工厂。
const myFactory = () => { return new BehaviorSubject<string>('') };
providers: [
{ provide: MyValueToken, useFactory: myFactory }
]
// Then, as proposed in the top-answer.
// consumer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.subscribe((my_value)=>this.title = my_value);
}
// producer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.next('my title value');
}
如果您不想使用 BehaviorSubject
,您可以提供一个带有 getter 和 setter 的简单 class。
class MyValue {
get value(): string {
return this._value;
}
set value(val: string) {
this._value = val;
}
private _value = '';
}
const MY_VALUE_TOKEN = new InjectionToken<MyValue>('MY_VALUE_TOKEN ');
// Provide class in either module or component providers array.
providers: [
{ provide: MY_VALUE_TOKEN , useClass: MyValue },
]
class MyComponent {
// Inject in component constructor
constructor(
@Inject(MY_VALUE_TOKEN) private _myValue: MyValue,
) {
// Access current value
console.log(this._myValue.value);
// Set new value
this._myValue.value = 'new value';
}
}
关于为什么...
既然您也想知道为什么要注入静态结构,Angular Material 经常这样做是为了向组件提供配置。
例如。 Chips control:
@NgModule({
providers: [
{
provide: MAT_CHIPS_DEFAULT_OPTIONS,
useValue: {
separatorKeyCodes: [ENTER, COMMA]
}
}
]
})
无需理解此数据代表什么,只需意识到您正在注入一个价值 { separatorKeyCodes: [ENTER, COMMA] }
的令牌 MAT_CHIPS_DEFAULT_OPTIONS
这将从您的 AppModule 或您定义它的任何模块或组件继承 - 就像任何其他可注入服务一样。这同样可以在您的 @Component
或 @Directive
定义中为单个组件(及其子组件)提供配置。
当然,当您的应用程序中的不同模块或组件需要不同的配置时,您可以将其注入到那里,只有子组件会继承它。
老实说,这样做似乎很痛苦,而不仅仅是在组件上设置一个值,但这就是很多 Angular Material 控件的工作方式。当然好处是你只做一次,所有的东西都会继承它。
Angular 依赖项注入让您可以使用令牌而不是服务来注入字符串、函数或对象 class。
我在我的模块中这样声明它:
providers: [{ provide: MyValueToken, useValue: 'my title value'}]
我是这样使用它的:
constructor(@Inject(MyValueToken) my_value: string) {
this.title = my_value;
}
但是,如何更新组件的值并让其他组件每次都获取新值?换句话说,我想模拟使用 BehaviorSubject
之类的东西来发出和接收值的功能。
如果这不可能,那么如果它们仅提供静态数据,那么这些注入标记值的用途是什么,因为我可以简单地在我的组件中声明静态值并直接使用它。
您可以使用 BehaviorSubject
而不是不可变的原语,然后在一个组件中访问和更新它并在另一个组件中订阅:
providers: [{ provide: MyValueToken, useValue: new BehaviorSubject('')}]
// consumer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.subscribe((my_value)=>this.title = my_value);
}
// producer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.next('my title value');
}
除了精灵:
如果您有一个用例,其中每个消费者都需要自己的 BehaviourSubject 实例。 (我碰巧在这个用例中)。确保定义工厂。
const myFactory = () => { return new BehaviorSubject<string>('') };
providers: [
{ provide: MyValueToken, useFactory: myFactory }
]
// Then, as proposed in the top-answer.
// consumer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.subscribe((my_value)=>this.title = my_value);
}
// producer
constructor(@Inject(MyValueToken) my_value: BehaviorSubject) {
my_value.next('my title value');
}
如果您不想使用 BehaviorSubject
,您可以提供一个带有 getter 和 setter 的简单 class。
class MyValue {
get value(): string {
return this._value;
}
set value(val: string) {
this._value = val;
}
private _value = '';
}
const MY_VALUE_TOKEN = new InjectionToken<MyValue>('MY_VALUE_TOKEN ');
// Provide class in either module or component providers array.
providers: [
{ provide: MY_VALUE_TOKEN , useClass: MyValue },
]
class MyComponent {
// Inject in component constructor
constructor(
@Inject(MY_VALUE_TOKEN) private _myValue: MyValue,
) {
// Access current value
console.log(this._myValue.value);
// Set new value
this._myValue.value = 'new value';
}
}
关于为什么...
既然您也想知道为什么要注入静态结构,Angular Material 经常这样做是为了向组件提供配置。
例如。 Chips control:
@NgModule({
providers: [
{
provide: MAT_CHIPS_DEFAULT_OPTIONS,
useValue: {
separatorKeyCodes: [ENTER, COMMA]
}
}
]
})
无需理解此数据代表什么,只需意识到您正在注入一个价值 { separatorKeyCodes: [ENTER, COMMA] }
MAT_CHIPS_DEFAULT_OPTIONS
这将从您的 AppModule 或您定义它的任何模块或组件继承 - 就像任何其他可注入服务一样。这同样可以在您的 @Component
或 @Directive
定义中为单个组件(及其子组件)提供配置。
当然,当您的应用程序中的不同模块或组件需要不同的配置时,您可以将其注入到那里,只有子组件会继承它。
老实说,这样做似乎很痛苦,而不仅仅是在组件上设置一个值,但这就是很多 Angular Material 控件的工作方式。当然好处是你只做一次,所有的东西都会继承它。