问题:
我需要有关如何在 Angular 中编写机制以在我的应用程序中全局设置组件的“外观和感觉”的指导。请注意,我正在努力学习@ngrx/平台 https://github.com/ngrx/platform我认为这将是一个有趣的设计约束;然而,如果它没有意义,我愿意放弃它。
分解:
我正在开发一个包含许多组件的应用程序。我的应用程序中的每个组件当前都有 3 种可能的“外观和感觉 (L&F)”:
请注意,可能会有基于更细粒度时间的颜色光谱.
这些 L&F 根据当前用户一天中的时间设置,例如,如果用户当前时间是上午 7 点,则计算出的 L&F 将设置为“早上”。我正在内部跟踪这个状态ngrx/商店 https://github.com/ngrx/platform/blob/master/docs/store/README.md一个名为的角度模块SundialModule
and gnomon
是减速器和动作的机制getting
or setting
state:
日晷/减速器/gnomon.ts:
import * as gnomon from '../actions';
export interface State {
currentHour: number,
}
const initialState: State = {
currentHour: new Date().getHours()
};
export function reducer(state = initialState,
action: gnomon.Actions) {
console.log(action, 'action');
switch(action.type) {
case gnomon.MORNING:
return {
...state,
currentHour: 6,
};
case gnomon.AFTERNOON:
return {
...state,
currentHour: 12,
};
case gnomon.EVENING:
return {
...state,
currentHour: 7,
};
default:
return state;
}
}
现在我有一个角度属性指令 https://angular.io/guide/attribute-directives called [sundialTheme]
这将设置一个HostBinding('class') theme = 'light' https://angular.io/api/core/HostBinding在它所放置的元素上。
日晷/指令/theme.ts
@Directive({
selector: '[sundialTheme]'
})
export class SundialThemeDirective implements OnInit {
@HostBinding('class') theme = 'light';
private gnomon: Observable<any>;
constructor(private store: Store<fromGnomon.State>) {
this.gnomon = store.select<any>('gnomon');
}
ngOnInit() {
this.gnomon.subscribe((theme) => {
if(theme.currentHour >= 7 && theme.currentHour <= 11){
this.theme = 'sepia';
} else if( theme.currentHour >= 12 && theme.currentHour <= 18) {
this.theme = 'light'
} else {
this.theme = 'dark'
}
});
}
}
问题:我的应用程序中的每个组件都需要具有以下属性sundialTheme
;此外,每个组件都会订阅this.gnomon = store.select<any>('gnomon');
,感觉很贵/很严厉。最后,顺便说一句,每个组件都需要有我的sundialModule
注入每个功能模块,每个组件都需要一天中每个时间的主题集:
每个模板的组件就是一个例子。note: sundialTheme
属性指令:
<mh-pagination sundialTheme></mh-pagination>
<canvas glBootstrap class="full-bleed" sundialTheme></canvas>
<running-head [state]="(state$ | async)" sundialTheme></running-head>
<menu-navigation sundialTheme></menu-navigation>
<folio sundialTheme></folio>
<mh-footer sundialTheme></mh-footer>
每个功能模块都有一个SundialModule
依赖性:
@NgModule({
imports: [
SundialModule
],
})
export class MenuModule {
}
每个组件的 styleUrls 都带有sundial-links
:
注意丑陋的 sundial-morning.scss
@Component({
selector: 'running-head',
templateUrl: 'running-head.component.html',
styleUrls: [
'running-head.component.scss',
'../../../components/sundial/sundial-morning.scss', // This !
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RunningHeadComponent {
}
最后我还得到了其他方法:
1)由于我使用的是 Angular CLI,因此我可以全局添加样式,并使用指令在主体上设置类。这似乎违反了任何类型的 Web 组件标准。
2)我可以在每个组件中使用工厂加载器styleUrls:[]
;我还不清楚如何实施。
3)我可以遵循材料设计组件架构,将主题直接添加到组件中,这不会感觉很干燥? (不过我还没有研究太深入)
4)我可以为每个组件制作一个自定义装饰器(可能可行,但我不确定如何实现)
还有其他建议吗?有推理的最佳实践吗?