2016-10-02 95 views
2

我有一个观察的 - loading$ - 输出真正当我想显示在UI加载覆盖,并当它的时间,以去除覆盖。可见性由一个CSS类控制。角2:根外变化的DOM元素AppComponent

当可观察发射真正,我想的CSS类添加到<body>,并删除它

HTML

<body class=""> 
    <my-app>Angular app goes here</my-app> 
</body> 

正如你所看到的,<body>是我Angular 2应用程序之外,所以我不能使用属性绑定更改类。这是我目前做的:

AppComponent.ts

loading$.subscribe(loading =>{ 
    if(loading) document.querySelector('body').classList.add('loading'); 
    else document.querySelector('body').classList.remove('loading'); 
}); 

这种运作良好。当loading$观测值发射时,loading类被添加/删除true/false。问题是我想在web worker中运行我的应用程序,这意味着无法访问DOM。另外,Angular建议不要直接操纵DOM。

如何使用Angular API更改<body>

Angular 2typescript 2rxjs 5 beta 12

PS:This question看起来很有希望,但关键的环节是死的。我也看到了几个与Beta发行工作的建议,但现在已经过时(example

+0

角允许您更改[页面标题](https://angular.io/docs/ts/latest/cookbook/set-document -title.html),当我们谈论有关Angular的外部元素的访问时。为什么从外部操纵DOM对你来说很重要?为什么不把它放在'my-app'中? – ktretyak

+0

@ktretyak当'body'有'loading'类时,显示一个加载覆盖图。 'index.html'默认将类设置为ON。我希望网页显示这个加载覆盖图,直到它准备好用户输入为止(直到加载了Angular根组件)。所以一旦组件加载,我使用'Angular'去除CSS类。同样,当用户离开组件时,我在'CanDeactivate'钩子上启用'loading',并在加载下一个路由时(在OnInit钩子中)禁用它。 – BeetleJuice

+0

您可以使根组件非常轻量级(如''),并且在加载时不必等待。 – ktretyak

回答

1

尝试做这样的:

<my-app> 
    <div class="your-class-for-loading"></div> 
</my-app> 

my-app准备就绪,DIV将被自动删除。

+0

谢谢。你的灵感来源于我的解决方案(我将它写为答案) – BeetleJuice

1

@ktretyak的解决方案为我工作。基本上,而是采用<body>我把取loading类中<my-app>

的index.html

<body> 
    <my-app> 
     <div id="overlay" class="loading"></div> 
    </my-app> 
</body> 

CSS

#overlay { 
    position:fixed; 
    top:0; 
    left:0; 
    bottom:0; 
    right:0; 
    display:none; 
} 
#overlay.loading { 
    display:block 
} 

由于CSS样式的DIV,和启用了loading这一事实,则会在Javascript加载时显示叠加层,并显示Angular bootstraps。

一旦加载了Angular<my-app>中的所有内容都将替换为AppComponent模板。正如我在OP下面的评论中所解释的那样,我需要持续访问这个加载覆盖,因为我在加载新路由时显示它(当用户从​​一个路由组件导航到另一个时)。所以我不得不在模板中包括同一覆盖DIV

app.component.html

<div id="overlay" [class.loading]="showLoading"></div> 
<router-outlet></router-outlet> 

现在,当我loading$观察到的火灾,我改变了一个类属性showLoading和角负责更新因为它覆盖现在的AppComponent

部分app.component.ts

// set to true to show loading overlay. False to hide 
showLoading:boolean = true; 

ngOnInit(){ 
    // show/hide overlay depending on value emitted 
    loading$.subscribe(loading => this.showLoading = loading); 
} 
2

如果您想在引导应用程序的过程中通过DOM替换获得不间断的动画,请使用以下方法。

将覆盖图放在my-app元素之后。当数据被加载初始呼叫(闪仍是可见的,当屏幕不能完全呈现)

@HostBinding('class.ready') ready: boolean = false; 

更改属性:

<my-app></my-app> 
<div id="overlay"></div> 

的主要成分app.component.ts添加@HostBindingclass.ready

constructor(private contextService: ContextService) { 
    someService.initCall().then(r => this.ready = true); 
} 

使用CSS来隐藏装载机:

my-app.ready + .overlay { 
    animation: hideOverlay 1s forwards; 
} 

@keyframes hideOverlay { 
    0% { 
     opacity: 1; 
    } 

    100% { 
     opacity: 0; 
     visibility: hidden; 
    } 
} 
+0

没有测试过,但它确实很聪明! – BeetleJuice