如何从 Angular 2 中的嵌套组件更改父背景图像?

How can you change a parent background image from a nested component in Angular 2?

对于我应用程序中的每个路由,我都需要更改父背景图像。我在每个嵌套组件中使用样式 属性 来实现此目的,在每个组件中将 ViewEncapsulation 设置为 None 以便它具有全局效果。这行得通,但问题是当我浏览应用程序时,我在 head 标签中获得了这种样式的多个实例:

<style>...</style>
<style>...</style>

子组件的代码如下:

import {Component, Output, EventEmitter} from '@angular/core';
import {ViewEncapsulation} from '@angular/core';

@Component({
    selector: '',
    templateUrl:'app/home.component.html',
    styles: [`
              .hero-unit {
                  background:url('/app/assets/images/hero-01.png');
                  width:100%;
                  height:540px;
                  background-size: cover;
                  background-repeat: no-repeat;
                  background-position: 50% 50%;
              }
            `],

    encapsulation: ViewEncapsulation.None
})
export class HomeComponent {

}

一个覆盖另一个,这没关系,直到您尝试导航回上一页,效果停止工作。我的问题是,有没有一种方法可以在我离开该组件后删除样式 属性 并在我导航回来时将其重新插入。或者,有没有更好的方法来根据路线换出背景图像。我很难在 Angular 2 中找到完成如此简单任务的最佳方法。谢谢。

您可以使用路由器数据或服务。

路由器解决方案

将图片URL放入路由数据中:

{ path:      'child1', 
  component: Child1Component,
  data:      { imageUrl: '/app/assets/images/hero-02.png' }
}

然后父组件可以订阅路由事件,提取URL并更新样式属性:

import {Component, Renderer, ElementRef} from '@angular/core';
import {Router, ActivatedRoute, NavigationEnd} from '@angular/router';

@Component({
  template: `<section>
    UserComponent content here, if any.
    <nav>
       <a [routerLink]="['./']">Activity</a>
       <a [routerLink]="['profile']">Profile</a>
       - child routes
    </nav>
    <div class="child-view">
      <router-outlet></router-outlet>
    </div>
    <section>`
})
export class UserComponent {
  constructor(private router: Router, private route: ActivatedRoute, 
    private renderer:Renderer, private elref:ElementRef) {}
  ngOnInit() {
    this.router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe(_ => { 
          let childRouteSnapshot = this.route.firstChild.snapshot;
          let url = childRouteSnapshot.data.imageUrl;
          this.renderer.setElementStyle(this.elref.nativeElement.childNodes[0],
            'background-image', 'url(' + url + ')');
      })
  }
}

这是一个有效的 Plunker。 (注意plunker中的部分代码只是半途转了RC5,上面展示的代码都是RC5。)

我不得不使用 childNodes[0] 因为在我的示例中 elref 被设置为 ng-component 而不是 <section>.

服务解决方案

使用共享服务。请参阅食谱部分 Parent and children communicate via a service。子组件在父组件订阅的 observable/subject 上发布事件(即 URL 图像字符串)。