【问题标题】:Angular 2, How to pass options from parent component to child component?Angular 2,如何将选项从父组件传递给子组件?
【发布时间】:2016-06-10 03:29:27
【问题描述】:

我一直在寻找解决方案。我从@Input、@Query、dynamicContentLoader、@Inject、@Inject(forwardRef(()) 中尝试了很多不同的东西,但还没有弄清楚。

我的示例结构:

parent.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'my-app',
    directives : [Child],
    template   : `<parent-component></parent-component>`
})

export class Parent
{
    private options:any;

    constructor()
    {
        this.options = {parentThing:true};
    }
}

child.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'parent-component',
    template   : `<child-component></child-component>`
})

export class Child
{
    constructor(private options:any) <- maybe I can pass them in here somehow?
    {
        // what I am trying to do is get options from
        // the parent component at this point
        // but I am not sure how to do this with Angular 2
        console.log(options) <- this should come from the parent

        // how can I get parent options here?
        // {parentThing:true}
    }
}

这是我当前在 DOM 中的 HTML 输出,所以这部分工作正常

<parent-component>
   <child-component></child-component>
</parent-component>

问题总结:

如何将选项从父组件传递到子组件并在子构造函数中使用这些选项?

【问题讨论】:

  • 简单绑定有什么问题? @Input() 在孩子和&lt;child [someInput]="someOption"?
  • 我已经看过很多次了。这很可能是解决方案。问题是无论出于何种原因,我都不明白一切应该如何联系在一起。我用@Input 搞砸了一段时间。但我认为我很难理解所有发生的隐含的事情以及如何让它正常工作。
  • 基本上我已经尝试了所有这些.. @Input, @Query, dynamicContentLoader, @Inject, @Inject(forwardRef(() 但我无法让他们做我想做的事情。所以我并不是说他们不能。但或多或少,我尽量减少了我的问题,以显示我想要达到的最终结果类型。其中之一可能是解决方案。
  • 刚刚看到,为什么需要它们在构造函数中可用?
  • 查看我更新的答案,但为什么在构造函数中需要它?

标签: javascript angular


【解决方案1】:

Parent to child 是最简单的形式,但它在构造函数中不可用,仅在 ngOnInit()(或更高版本)中可用。

这只需要子组件中的@Input() someField;,并且使用绑定可以将其从父组件传递给子组件。 parent 中的更新在 child 中更新(不是另一个方向)

@Component({
  selector: 'child-component',
  template'<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  @Input() someValueFromParent:string;

  ngOnInit() {
    console.log(this.someValue);
  }
}

@Component({
  selector: 'parent-component',
  template: '<child-component [someValueFromParent]="someValue"></child-component>'
})
class ParentComponent {
  someValue:string = 'abc';
}

要使其在构造函​​数中可用,请使用共享服务。共享服务被注入到两个组件的构造函数中。为了使注入工作,服务需要在父组件或更高版本中注册,而不是在子组件中。这样两者都得到相同的实例。 在 parent 中设置一个值并在 client 中读取它。

@Injectable()
class SharedService {
  someValue:string;
}

@Component({
  selector: 'child-component',
  template: '<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  constructor(private sharedService:SharedService) {
    this.someValue = sharedService.someValue;
  }
  someValue:string = 'abc';
}

@Component({
  selector: 'parent-component',
  providers: [SharedService],
  template: '<child-component></child-component>'
})
class ParentComponent {
  constructor(private sharedService:SharedService) {
    sharedService.someValue = this.someValue;
  }
  someValue:string = 'abc';
}

更新

没有太大区别。对于 DI,只能使用构造函数。如果你想注入一些东西,它必须通过构造函数。 ngOnInit() 在发生额外的初始化(比如正在处理的绑定)时由 Angular 调用。例如,如果您进行网络调用,是否在ngOnInit 的构造函数中进行调用并不重要,因为无论如何都会安排稍后调用服务器(异步)。当前同步任务完成后,JavaScript 会查找下一个计划任务并处理它(依此类推)。因此,无论您将其放在何处,都可能是在构造函数中发起的服务器调用实际上是在ngOnInit() 之后发送的。

【讨论】:

  • 我很抱歉拖了这个。您能否详细说明ngOnInit()constructor() 之间的区别(或知道任何好的资源)我的所有组件是否都需要一个构造函数?
  • 感谢您的解释和回答。这消除了我的很多困惑。这也解释了为什么 @Input() 在构造函数中不起作用。
【解决方案2】:

您可以使用@Input 参数:

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

@Component({
  selector   : 'parent-component',
  template   : `<child-component></child-component>`
})
export class Child {
  @Input()
  options:any;

  ngOnInit() {
    console.log(this.options);
  }
}

注意options 的值在ngOnInit 中可用,而不在构造函数中。查看组件生命周期钩子以获取更多详细信息:

并提供如下所述的选项:

import {Component} from 'angular2/core';

@Component({
  selector   : 'my-app',
  directives : [Child],
  template   : `<parent-component [options]="options"></parent-component>`
})
export class Parent {
  private options:any;

  constructor() {
    this.options = {parentThing:true};
  }
}

如果你想实现自定义事件:child 触发一个事件并且 parent 注册被通知。使用@Output

【讨论】:

  • 感谢您的回复,我在发布之前实际上已经尝试过了。只是再次尝试验证。 this.options 以未定义的形式返回。
  • 抱歉,我是倒着看的。我看到您发布的答案基本上与@Gunter 相同。但是我不得不接受一个。所以我选择了他,因为他很好地解释了constructor()ngOnInit() 以及在需要时访问constructor() 的信息的替代解决方案。不过感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 2017-08-04
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
  • 2022-11-24
相关资源
最近更新 更多