Angular2:子组件访问父组件 class variable/function

Angular2: child component access parent class variable/function

我在父组件中有一个可能会被子组件更改的变量,父组件将在视图中使用此变量,因此必须传播更改。

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

@Component({selector: 'parent'})
@View({
    directives: [Child],
    template: `<childcomp></childcomp>`
})
class Parent {
    public sharedList = new Array();
    constructor() {
    }
}


@Component({selector: 'child'})
@View({template: `...`})
class Child {
    constructor() {
        //access 'sharedList' from parent and set values
        sharedList.push("1");
        sharedList.push("2");
        sharedList.push("3");
        sharedList.push("4");
    }
}

基本上你不能直接从父级访问变量。你通过事件来做到这一点。组件的输出 属性 对此负责。我建议阅读 https://angular.io/docs/ts/latest/guide/template-syntax.html#input-and-output-properties

如果您将输入 属性 数据绑定与 JavaScript 引用类型(例如,Object、数组、日期等)结合使用,则 parent 和 child 都将引用 same/one object。 parent 和 child 都可以看到您对共享 object 所做的任何更改。

在 parent 的模板中:

<child [aList]="sharedList"></child>

在child中:

@Input() aList;
...
updateList() {
    this.aList.push('child');
}

如果你想在构造 child 时将项目添加到列表中,请使用 ngOnInit() 挂钩(而不是 constructor(),因为 data-bound 属性不是在那一点初始化):

ngOnInit() {
    this.aList.push('child1')
}

这个 Plunker shows a working example,在 parent 和 child 组件中都有按钮,它们都可以修改共享列表。

请注意,在 child 中您不得重新分配引用。例如,不要在 child 中这样做: this.aList = someNewArray; 如果这样做,那么 parent 和 child 组件将分别引用两个不同的数组。

如果你想共享原始类型(即字符串、数字、布尔值),你可以将其放入数组或 object(即放入引用类型),或者你可以 emit() 来自 child 的事件,只要原始值发生变化(即让 parent 侦听自定义事件,而 child 将有一个 EventEmitter 输出 属性。有关更多信息,请参阅@kit 的回答。)

更新 2015/12/22:Structural Directives 指南中的 heavy-loader 示例使用了我上面介绍的技术。 main/parent 组件有一个 logs 数组 属性 绑定到 child 组件。 child 组件 push() 到该数组,parent 组件显示该数组。

像 NgModel 对 NgForm 做的小把戏怎么样?您必须将 parent 注册为提供者,然后将 parent 加载到 child.

的构造函数中

这样一来,你就不必把 [sharedList] 放在你所有的 children 上了。

// Parent.ts
export var parentProvider = {
    provide: Parent,
    useExisting: forwardRef(function () { return Parent; })
};

@Component({
    moduleId: module.id,
    selector: 'parent',
    template: '<div><ng-content></ng-content></div>',
    providers: [parentProvider]
})
export class Parent {
    @Input()
    public sharedList = [];
}

// Child.ts
@Component({
    moduleId: module.id,
    selector: 'child',
    template: '<div>child</div>'
})
export class Child {
    constructor(private parent: Parent) {
        parent.sharedList.push('Me.');
    }
}

那么你的HTML

<parent [sharedList]="myArray">
    <child></child>
    <child></child>
</parent>

您可以在 Angular 文档中找到有关该主题的更多信息:https://angular.io/guide/dependency-injection-in-action#find-a-parent-component-by-injection

Angular2 文档中关于此主题的主要文章是:

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child

它涵盖以下内容:

  • 使用输入绑定将数据从 parent 传递到 child

  • 截取输入属性随setter

  • 变化
  • 拦截输入 属性 随着 ngOnChanges

  • 的变化
  • Parent 监听 child 事件

  • Parent 通过局部变量

  • 与 child 交互
  • Parent 调用 ViewChild

  • Parent 和 children 通过服务进行通信

你可以做到 在 parent 组件中声明:

get self(): ParenComponentClass {
        return this;
    }

在child组件中,引入ParenComponentClass后,声明:

private _parent: ParenComponentClass ;
@Input() set parent(value: ParenComponentClass ) {
    this._parent = value;
}

get parent(): ParenComponentClass {
    return this._parent;
}

然后在parent的模板中可以做

<childselector [parent]="self"></childselector>

现在从 child 您可以使用

访问 parent 的 public 属性和方法
this.parent