【问题标题】:Accessing Parent Component Data / Properties from a Child Component in Angular2从Angular2中的子组件访问父组件数据/属性
【发布时间】:2016-05-29 04:56:00
【问题描述】:

我“束手无策”,不知道该怎么做。我快哭了!

在使用 AngularJS 多年后,我正在尝试自学 Angular2 - 我有一个 Angular2 应用程序,它具有像所谓的 App 这样的顶级组件

@Component({
    selector: 'app', // <app></app>
    providers: [...FORM_PROVIDERS],
    directives: [...ROUTER_DIRECTIVES],
    template: require('./app.html')
})

@RouteConfig([
    {path: '/', component: Home, name: 'Home'},
    {path: 'about', component: About, name: 'About'},
    {path: 'profile', component: Profile, name: 'Profile'},
    {path: 'profile/:id', component: ForeignProfile, name: 'ForeignProfile'}
])

export class App {
    userStatus: UserStatus;
    userOnlineContacts: UserContact[];

    constructor(private userData: UserData) {
        this.userStatus = new UserStatus();
    }

    ngOnInit() {
         Observable.forkJoin([
            this.userData.getUserStatus(),
            this.userData.getContacts()
         ]).subscribe( (t) => {
                this.userStatus = t[0];
                this.userOnlineContacts = t[1].onlineContacts;
         });

        // Polling thing for this.userOnlineContacts...
        this.userData.pollContacts().subscribe(
            (data) => {
                this.userOnlineContacts = data.onlineContacts;
            });
    }
}

我在 index.html 中看起来像这样

<app>Loading...</app>

现在我正在使用 ng-router,所以在我的 app.html 中,我的 &lt;router-outlet&gt;&lt;/router-outlet&gt; 标签嵌套在我的 HTML 中。所以我的子组件被注入到这些标签中——我从不将我的选择器标签放入 HTML 中(所以我假设我不能使用数据绑定传递数据。在&lt;router-outlet&gt;&lt;/router-outlet&gt; 中,当我导航到ForeignProfile 组件,子组件代码是这样的……

@Component({
    selector: 'foreign-profile',
    template: require('app/components/foreign-profile/foreign-profile.html'),
    providers: [],
    directives: [],
    pipes: []
})

export class ForeignProfile implements OnInit {

    userProfile: any;
    routeId: string;
    userPhotos: any;
    userInfo: any;

    constructor(private userData: UserData, private routeParams: RouteParams) {
        this.routeId = routeParams.get('id');
        this.userProfile = {}; // not sure why I need to put this here otherwise we have 'undefined' error
    }

    ngOnInit() {
        // Use forkJoin as we don't need order in the calls
        Observable.forkJoin([
            this.userData.getUserPhotos(this.routeId),
            this.userData.getUserInfo(this.routeId),
            this.userData.getUserBaseData(this.routeId)])
            .subscribe(t => {
                this.userPhotos = t[0];
                this.userInfo = t[1];
                this.userProfile = t[2];
                // do more stuff here

        });
    }
}

在这个组件中,我希望访问 App 组件的属性,例如this.userStatus & this.userOnlineContacts。我不想创建一个服务来进行重复的 HTTP 调用,我想将父属性直接注入子属性。在 AngularJS 中,我可以使用 $scope.$parent.userStatus 之类的东西。现在我研究了通过修改组件将父级(App)注入子级(ForeignProfile):

这是 ForeignProfile 组件

import {App} from '../../app'

@Component({
    // blah blah...
})

export class ForeignProfile implements OnInit {

    // code removed for example, easier to read
    userStatus: any;

    constructor(private userData: UserData, private routeParams: RouteParams, @Inject app:App) {
        // code removed for example, easier to read
        this.userStatus = app.userStatus;
    }

然后和父母一起……

import {Injectable, Component} from 'angular2/core';

@Injectable()
@Component({
    selector: 'app', // <app></app>

这让我的控制台发疯了。有人能解释一下我是如何从我的 ForeignProfile 组件中的 App 组件访问属性的吗?到目前为止,我已经浪费了几个小时!提前致谢。

【问题讨论】:

  • 只需使用共享服务在父母和孩子之间进行通信。有很多类似的问题。
  • @GünterZöchbauer,这就是为什么$scope 如此有用。这使共享服务的任何消费者负责利用其 API 所需的逻辑。这不适合 DRY 编程。父组件应该有一种合理的方式在不知道实现细节的情况下向任何子组件提供数据。 (例如vm.someProperty.someMethod(someVar))这应该得到支持,IMO。
  • 如果您使用$scope,您需要一些合同,以便客户端使用预定义的名称访问值。这就是服务类的用途,一个共同的合同。我认为这是正确的方法。但这就是它在类 Java 语言中的实现方式。在 JS 世界中这并不常见,但目前从动态语言到类型语言的转变非常强烈。

标签: dependency-injection typescript angular


【解决方案1】:

正如@Günter Zöchbauer 正确提到的,您必须使用角度服务概念在组件之间共享数据。

如果你仍然想访问你的 App 组件,你可以在 ForeignProfile 构造函数中这样做:

constructor(@Host() @Inject(forwardRef(() => App)) app: App)
{

}

【讨论】:

  • 太好了,我假设我从 'angular2/core' 导入 @Host@InjectforwardRef
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
  • 2020-04-14
  • 2019-11-23
  • 2016-02-02
  • 1970-01-01
  • 2017-03-17
相关资源
最近更新 更多