Angular 2:更改 DOM 根 AppComponent 之外的元素

Angular 2: change DOM elements outside the root AppComponent

我有一个 observable -- loading$ -- 当我想在 UI 和 false 何时删除该覆盖层。可见性由 CSS class.

控制

当 Observable 发出 true 时,我想将 CSS class 添加到 <body>,并在 [=] 上删除它44=]假.

html

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

如您所见,<body> 在我的 Angular 2 应用程序之外,因此我无法使用 属性 绑定来更改 class。这就是我目前所做的:

AppComponent.ts

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

这很好用。当 loading$ observable 发出 true/false 时,loading class 是 added/removed。问题是我想在 Web Worker 中 运行 我的应用程序,这意味着无法访问 DOM。另外,Angular 建议不要直接操作 DOM。

如何使用 Angular API 来更改 <body>

Angular 2typescript 2rxjs 5 beta 12

PS: looks promising, but the key link is dead. I've also seen a couple of suggestions that worked with Beta releases but are now obsolete (example)

尝试这样做:

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

my-app准备就绪后,div将自动删除。

@ktretyak 的解决方案对我有用。基本上,我没有使用 <body>,而是将 loading class 放在 <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 样式,以及启用 loading 启动的事实,在 Javascript 加载和 Angular 引导程序时显示叠加层。

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

中包含相同的叠加层 div

app.component.html

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

现在,当我的 loading$ observable 触发时,我更改 class 属性 showLoading 并且 Angular 负责更新叠加层,因为它是现在是 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);
}

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

将叠加层放在 my-app 元素之后。

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

在主成分class.ready中添加@HostBindingapp.component.ts:

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

在初始调用加载数据时更改 属性(当您的屏幕未完全呈现时,启动画面仍然可见)。

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;
  }
}