Я хочу разделить значение между всеми моими компонентами (которые не обязательно связаны между собой), используя службу.
В Интернете есть несколько примеров, но у меня это не работает, я не знаю, что я сделал не так.
Кроме того, многие примеры основаны на старых версиях Angular, тогда как я хотел бы использовать для этого современные методы.
На данный момент у меня есть эти 3 файла, и я хочу поделиться значением «Тема»:
theme.service.ts:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ThemeService {
private _theme: 'light'|'dark' = 'light';
public get Theme() {
return this._theme;
}
public set Theme(theme: 'light'|'dark') {
this._theme = theme;
}
constructor() { }
}
приложение.компонент.ц:
import { Component, AfterViewInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ThemeService } from './services/theme.service';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
providers: [ThemeService],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent implements AfterViewInit {
constructor(private themeService: ThemeService) { }
ngAfterViewInit() {
console.info("app.component:", this.themeService.Theme);
this.themeService.Theme = "dark";
console.info("app.component:", this.themeService.Theme);
}
}
мойкомпонент.компонент.ц:
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { ThemeService } from '../../services/theme.service';
@Component({
selector: 'app-mycomponent',
standalone: true,
imports: [],
providers: [ThemeService],
templateUrl: './mycomponent.component.html',
styleUrl: './mycomponent.component.scss'
})
export class MyComponent implements AfterViewInit {
constructor(private themeService: ThemeService) { }
ngAfterViewInit() {
console.info("mycomponent.component:", this.themeService.Theme);
}
}
Я хотел бы получить такой результат:
app.component: light
app.component: dark
mycomponent.component: dark
Но у меня есть это:
app.component: light
app.component: dark
mycomponent.component: light
Я предполагаю, что два компонента используют разные экземпляры службы. Как мне сделать так, чтобы служба использовалась совместно между ними?
Не добавляйте ThemeService
в массивы providers
ваших компонентов. Сервис уже есть providedIn: 'root'
, а это значит, что у вас уже есть синглтон для приложения. Если вы добавите службу в массив providers
для компонента, вы создадите вторую копию, о которой будет знать только этот компонент.
См. раздел Внедрение зависимостей и иерархия инжекторов руководства Начало работы с автономными компонентами (выделено мной):
Приложения Angular могут настроить внедрение зависимостей, указав набор доступных поставщиков. В типичном применении имеется два разных типа инжекторов:
- модуль-инжектор с поставщиками, настроенными в
@NgModule.providers
или@Injectable({providedIn: "..."})
. Эти поставщики всего приложения видны всем компонентам, а также другим службам, настроенным в инжекторе модулей.- узлы-инжекторы настроены в
@Directive.providers
/@Component.providers
или@Component.viewProviders
. Эти поставщики видны только данному компоненту и всем его дочерним элементам.