【问题标题】:Angular 2 observable subscription not triggeringAngular 2 observable 订阅未触发
【发布时间】:2016-10-28 06:33:15
【问题描述】:

我在订阅未触发的 observable 时遇到问题。

我有一个使用侧导航布局指令的布局,如下所示:

<md-sidenav-layout class="nav-bar">


    <md-sidenav #start>
        <nav>
            <a [routerLink]="['/home']">Home</a>
        </nav> 
        <button md-button (click)="start.close()">Close</button>
    </md-sidenav>

    <router-outlet></router-outlet>

</md-sidenav-layout>

我需要做的是从路由器插座显示的组件中打开侧导航。

这样的组件可能如下所示:

@Component({

    providers: [SidenavService, MdIconRegistry],
    directives: [MdIcon],
    templateUrl: `<md-icon (click)="toggleSidenav()">menu</md-icon>`,
    styleUrls: ["./home.component.scss"]
})

export class Home {

    myColor: string;

    constructor(private sidenavService: SidenavService) {
        this.myColor = "primary";

        this.sidenavService.getSidenavObs().subscribe(state => {console.log("state change")});
    }


    toggleSidenav() {

        this.sidenavService.toggleSidenav("open");
    }

}

我创建了一个服务,它返回一个像这样的 observable:

@Injectable()
export class SidenavService {

    private toggle = new Subject<string>();
    private toggleObs = this.toggle.asObservable();

    getSidenavObs() {
        return this.toggleObs;
    }

    toggleSidenav(state: string) {
        this.toggle.next(state);
    }

}

最后是父类的代码(属于侧导航布局HTML):

@Component({
  providers: [MdSidenav, SidenavService],
  directives: [ROUTER_DIRECTIVES, MD_SIDENAV_DIRECTIVES, MD_BUTTON_DIRECTIVES],
  selector: "app",
  templateUrl: "app.html",
  styleUrls: ["./app.scss"],
})

export class App {

  subscription: Subscription;

  constructor(private sidenavService: SidenavService, private sidenav: MdSidenav) {
    this.subscription = sidenavService.getSidenavObs().subscribe( status => {
      console.log("state change");
      sidenav.open();
    }, error => {
      console.log(error);
    }, () => {
      console.log("completed");
    });
  }
}

现在我的问题是 App 组件中的订阅没有触发,但是 Home 组件中的订阅(这是路由器插座显示的内容)按预期触发。

我错过了什么吗?

我遵循了这个指南:https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    同一个服务实例不会在您的 App 和 Home 组件之间共享,因为您已将 SidenavService 列为两者的提供者。

    当您在 Component 装饰器的 providers 条目中定义服务提供者时,该服务随后可用于该组件及其所有子组件作为单例,这意味着将使用相同的服务实例。

    如果您在子组件中重新定义提供者,它将创建服务的新实例,并且不再与其父/祖先共享相同的服务实例。

    如果您在 App 和 Home 组件中都使用 SidenavService 并且需要相同的实例,则应仅在 App 组件中提供它,并将其从 Home 的 providers 条目中删除。

    有关 DI 的更多信息,请阅读以下链接: https://angular.io/docs/ts/latest/guide/dependency-injection.html https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

    【讨论】:

    • 谢谢迈克尔!!你救了我
    • 太好了,对我帮助很大!
    【解决方案2】:

    问题在于,与其他框架相反,Angular 似乎并没有强制 Services 默认为 singletons。

    因此,当您声明每个Component 拥有自己的Service 实例时,您会遇到这种情况。这导致每个实例具有不同的属性(toggle 和toggleObs)。示意图:

    App -> SidenavService [实例 A]

    首页 -> SidenavService [实例 B]

    您需要更改您的声明以匹配 单例服务,如 Angular Documentation 中所述。这导致在所有Components 中仅共享Service 的单个实例。示意图:

    App -> SidenavService [实例 A]

    首页 -> SidenavService [实例 A]

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2017-03-24
      • 2018-10-03
      相关资源
      最近更新 更多