Angular 2 - 在父组件初始化后将数据传递给子组件

9 浏览
0 Comments

Angular 2 - 在父组件初始化后将数据传递给子组件

我有一个父组件,通过服务从服务器获取数据。我需要将其中的一些数据传递给子组件。

我一直试图用通常的@Input()来传递这些数据,但是正如我所预料的,我在子组件中得到的数据是undefined

示例

父组件

@Component({
    selector: 'test-parent',
    template: `
        
    `
})
export class ParentComponent implements OnInit {
    data: any;
    ngOnInit() {
        this.getData();
    }
    getData() {
        // 调用服务并获取数据
        this.testService.getData()
            .subscribe(res => {
                this.data = res;
            });
    }
}

子组件

@Component({
    selector: 'test-child',
    template: `
        
    `
})
export class ChildComponent implements OnInit {
    @Input() childData: any;
    ngOnInit() {
        console.log(childData); // 输出undefined
    }
}

我保持示例简单,以展示我的意图。我的问题是是否可能在初始化之后将数据传递给子组件。我不确定,但是双向数据绑定是否有助于解决这个问题?

更多调查

根据已发布的答案,我尝试使用ngOnChanges生命周期钩子。我遇到的问题是当数据更新时,ngOnChanges函数不会触发。我认为这是因为数据是一个对象,所以改变没有被检测到。

子组件中更新后的代码

@Component({
    selector: 'test-child',
    template: `
        
    `
})
export class ChildComponent implements OnChanges {
    @Input() childData: any;
    ngOnChanges() {
        console.log(childData); // 输出undefined
    }
}

我尝试了一下Angular团队展示生命周期钩子的Plunker上的实时例子。在测试中,我更新了OnChangesComponent以传递一个对象,正如例子中所示,当更新一个对象时,ngOnChanges没有检测到更改。(这也在这个问题中显示出来)

https://plnkr.co/edit/KkqwpsYKXmRAx5DK4cnV

似乎ngDoCheck可以帮助解决这个问题,但我认为从长远来看,这不会提高性能,因为每次更改都会被这个生命周期钩子检测到。

我也知道我可能可以使用@ViewChild()来访问子组件并设置我需要的变量,但是我认为对于这个用例来说,这并没有太多意义。

发布更多代码以更好地解释

父组件

@Component({
    selector: 'test-parent',
    template: `
        
            
        
        
            
        
        
    `
})
export class ParentComponent implements OnInit {
    data: any;
    numbersData: any;
    lettersData: any;
    ngOnInit() {
        this.getData();
    }
    getData() {
        // 调用服务并获取游戏选择的数据
        this.testService.getData()
            .subscribe(res => {
                this.data = res;
                setChildData(this.data);
            });
    }
    setChildData(data: any) {
        for(let i = 0; i < data.sections.length; i++) {
            if(data.sections[i].type === 'numbers') {
                this.numbersData = data.sections[i];
            }
            if(data.sections[i].type === 'letters') {
                this.lettersData = data.sections[i];
            }
        }
    }
    pickNumber(pickedNumbers: any[]) {
        this.pickedNumbers = pickedNumbers;
    }
    pickLetter(pickedLetters: any[]) {
        this.pickedLetters = pickedLetters;
    }
    submitSelections() {
        // 调用服务提交选择
    }
}

子组件

@Component({
    selector: 'test-child',
    template: `
        
    `
})
export class ChildComponent implements OnInit {
    @Input() childData: any;
    @Output() onSelection = new EventEmitter;
    pickedItems: any[];
    // 用于点击事件
    pickItem(item: any) {
        this.pickedItems.push(item.number);
        this.onSelection.emit(this.pickedItems);
    }
}

这大致是我拥有的代码。基本上,我有一个父组件处理子组件的选择,然后我将这些选择提交给服务。我需要将某些数据传递给子组件,因为我试图使子组件返回的对象格式符合服务的期望。这样做可以帮助我避免在父组件中创建服务所期望的整个对象。此外,它使得子组件在发送回服务所期望的内容方面具有重用性。

更新

我很感激用户仍然在这个问题上发布答案。请注意,上面发布的代码对我有用。我遇到的问题是在一个特定的模板中有一个拼写错误,导致数据为undefined

希望它能对你有所帮助 🙂

0
0 Comments

Angular 2中父组件向子组件传递数据时,出现了childData未定义的问题。原因是在子组件的ngOnChanges方法中,没有使用this关键字引用childData。

解决方法是在ngOnChanges方法中使用this关键字引用childData,如下所示:

ngOnChanges() {
    console.log(this.childData); // 使用this引用
}

这样就能正确地输出childData的值了。

0
0 Comments

问题的原因是在父组件(Parent component)初始化之后将数据传递给子组件(Child component)时,子组件无法正确获取到数据。解决方法是使用ngOnChanges方法来获取数据。

ngOnChanges是Angular的生命周期钩子方法之一,在组件或指令的输入属性(input properties)发生变化时被调用。

ngOnChanges示例代码如下:

ngOnChanges() {
   if(!!childData){         
        console.log(childData);         
   }
}

ngOnChanges方法只有在整个对象被更改时才会触发,如果只想更新绑定对象的属性而不是整个对象,有两种方法可以解决:

1. 直接在模板中绑定属性,确保使用?来处理可能为空的情况,例如:{{childData?.propertyName}}

2. 创建一个依赖于childData对象的get属性,例如:

get prop2(){
  return this.childData.prop2;
}

以下是完整示例代码:

import { Component, Input } from '/core';
@Component({
  selector: 'my-app',
  template: `

Hello {{name}}

` }) export class AppComponent { name = 'Angular'; childData = {}; constructor(){ // 2秒后设置childData setTimeout(() => { this.childData = { prop1 : 'value of prop1', prop2 : 'value of prop2' } }, 2000) } } @Component({ selector: 'child-component', template: ` prop1 : {{childData?.prop1}} prop2 : {{prop2}} ` }) export class ChildComponent { @Input() childData: {prop1: string, prop2: string}; get prop2(){ return this.childData.prop2; } }

以上代码的运行结果可以在Plunker上查看:[Plunker](http://plnkr.co/edit/DxNfkDdg2ClNVzI6HMLf?p=preview)

希望这可以帮到你!感谢你的回答,它似乎指导了我正确的方向。我现在唯一遇到的问题是,如果数据是一个"简单的"字符串,ngOnChanges会检测到变化,但如果是一个对象,出于某种原因它会保持undefined。

更新答案:

再次感谢你的帮助...我刚刚发现问题所在。在模板变量中有一个拼写错误,所以它总是undefined。之前没有意识到!现在看起来好像可以了,显然我不需要任何ngOnChanges或getter来处理对象...现在看起来没问题了。

0
0 Comments

问题出现的原因是由于在父组件初始化时,数据是未定义的。解决方法是使用*ngIf='data'来延迟加载数据,或者在组件上实现ControlValueAccessor并使用ngModel传递数据。

首先,我们可以使用*ngIf='data'来延迟加载数据。这意味着只有当data有值时,才会渲染子组件。代码如下:

另一种解决方法是在组件上实现ControlValueAccessor,并使用ngModel和ngModelChange来传递数据。代码如下:


*ngIf='data'可能并不是最佳的解决方法。对于我来说,它并没有起作用。相反,ngOnChanges是一个有效的解决方法。通过在子组件中实现ngOnChanges生命周期钩子函数,我们可以在父组件传递数据给子组件时进行相应的操作。

0