范围html元素

时间:2016-02-09 21:07:05

标签: typescript singleton angular

最近我开始使用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;
    }
}

(支持twofuckingdevelopers

现在,当我尝试在Component

中访问它时,此功能非常有用
export class Slider { 

    constructor() {

    }

    mousedown(event) {
        UIManagerService.getInstance().setHoldingUI(true);
        console.log(UIManagerService.getInstance().getHoldingUI());
    }
}

提前致谢,

Nkmol

3 个答案:

答案 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);
    }
}

这不是最干净的解决方案,但它可以完成这项工作。现在我保留这个答案直到有更好的答案