最近我开始使用Angular 2和TypeScript,我想知道如何在整个网页上访问Singleton Class
。
我正在做的是UIManagerService
目前仅持有boolean
以检查是否正在访问UI组件。
使用此boolean
我想在我的<html>
元素上添加一个类:
.noselect {
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
}
并像这样访问:
<html [class.noselect] = "UIManagerService.HoldingUI">
...
</html>
更多Components
最终会访问此Singleton class
。
我的方法
在其他语言中,我会将单例类用于类似管理器的类。这也是我的方法:
export class UIManagerService {
holdingUI:Boolean;
static instance : UIManagerService;
static isCreating: Boolean = false;
constructor() {
if(!UIManagerService.isCreating) {
throw new Error("You can't call new in singletong instance");
}
}
static getInstance() {
if(UIManagerService.instance == null) {
UIManagerService.isCreating = true;
UIManagerService.instance = new UIManagerService();
UIManagerService.isCreating = false;
}
return UIManagerService.instance;
}
setHoldingUI(value) {
this.holdingUI = value;
}
getHoldingUI() {
return this.holdingUI;
}
}
现在,当我尝试在Component
export class Slider {
constructor() {
}
mousedown(event) {
UIManagerService.getInstance().setHoldingUI(true);
console.log(UIManagerService.getInstance().getHoldingUI());
}
}
提前致谢,
Nkmol
答案 0 :(得分:2)
在angular2中,您无需执行任何特殊操作即可创建单件服务。默认情况下,它们是单身。所以请使用angular提供的服务概念。另外值得一提的是,你没有在样本Slider组件中使用依赖注入 - 由于种种原因这很糟糕。这两个问题都在这里深入描述:dependency injection in angular2。
要从组件访问服务公开的属性或方法,您可以在组件中创建一个简单的包装器属性/方法:
@Component(.....)
export class Slider
{
private m_service: UIManagerService;
constructor(service: UIManagerService)
{
this.m_service = service;
}
public test()
{
this.m_service.test();
}
}
并在bootstrap调用中:
自举( 应用, [ UIManagerService ]);
答案 1 :(得分:2)
同意已经给出的答案。
一个补充。
如果您希望Angular仍然使用您的getInstance
功能来创建您的服务(可能您希望稍后在其中添加更多逻辑而不仅仅是“新建”它),您可以这样做。
在ui.manager.service.ts
:
import {provide} from 'angular2/core';
export class UIManagerService {
holdingUI: boolean;
static instance : UIManagerService;
static isCreating: Boolean = false;
constructor() {
if(!UIManagerService.isCreating) {
throw new Error("You can't call new in singleton instance");
}
}
static getInstance(): UIManagerService {
if(UIManagerService.instance == null) {
UIManagerService.isCreating = true;
UIManagerService.instance = new UIManagerService();
UIManagerService.isCreating = false;
}
return UIManagerService.instance;
}
setHoldingUI(value): void {
this.holdingUI = value;
}
getHoldingUI(): boolean {
return this.holdingUI;
}
test(): void {
console.log("This is coming from UIManagerService");
}
}
export let UIManagerServiceProvider = provide(UIManagerService, {
useFactory: () => {
return UIManagerService.getInstance();
}
});
导出UIManagerServiceProvider
,调用getInstance
。
在您的主应用程序中(对我而言,它是app.component.ts):
import {Component} from 'angular2/core';
import {UIManagerService, UIManagerServiceProvider} from './ui.manager.service';
@Component({
selector: 'my-app',
template: `<h1 (mousedown)="_uiManagerService.test()">Angular 2 App</h1>`,
providers: [UIManagerServiceProvider]
})
export class AppComponent {
constructor(private _uiManagerService: UIManagerService) {
}
}
正如您在模板中看到的那样,您只需调用test
函数。
(mousedown)="_uiManagerService.test()"
答案 2 :(得分:0)
因为Angular 2似乎无法确定<html>
元素的范围,所以我只使用普通的javascript修复了这个问题:
<强> Slider.ts 强>
export class Slider {
constructor() {
}
mousedown() {
UIManagerService.getInstance().setHoldingUI(true);
}
mouseup() {
UIManagerService.getInstance().setHoldingUI(false);
}
}
不需要注射,因为我无法引导某些东西,因为它超出了范围。
<强> UIManagerService.ts 强>
export class UIManagerService {
holdingUI:Boolean;
htmlClass = 'noselect';
static instance : UIManagerService;
static isCreating: Boolean = false;
constructor() {
if(!UIManagerService.isCreating) {
throw new Error("You can't call new in singletong instance");
}
}
static getInstance() {
if(UIManagerService.instance == null) {
UIManagerService.isCreating = true;
UIManagerService.instance = new UIManagerService();
UIManagerService.isCreating = false;
}
return UIManagerService.instance;
}
setHoldingUI(value) {
if(value)
this.addHTMLClass();
else
this.removeHTMLClass();
this.holdingUI = value;
}
getHoldingUI() {
return this.holdingUI;
}
// Toggle specific class
toggleHtmlClass() {
document.documetElement.classList.toggle(this.htmlClass);
}
}
这不是最干净的解决方案,但它可以完成这项工作。现在我保留这个答案直到有更好的答案。