Angular 角度2父组件从子组件丢失输入绑定

Angular 角度2父组件从子组件丢失输入绑定,angular,angular2-template,Angular,Angular2 Template,我正在使用一个父组件,它引用了在Angular 2中播放音频文件的子组件。最初,我将向音频文件传递一个输入变量_audioState,其中包含一个字符串值“Listen”。单击音频按钮时,该值将变为“播放”,然后在音频文件播放完毕后变为“重播”。这些字符串值更改发生在音频子组件中 当在父组件中单击带有nextAudio函数的按钮时,我想将_audioState重新分配回“Listen”,但一旦子组件更改此值,输入绑定在父组件中就不起作用 我仍在学习Angular 2,不确定让它工作的最佳方式。我

我正在使用一个父组件,它引用了在Angular 2中播放音频文件的子组件。最初,我将向音频文件传递一个输入变量_audioState,其中包含一个字符串值“Listen”。单击音频按钮时,该值将变为“播放”,然后在音频文件播放完毕后变为“重播”。这些字符串值更改发生在音频子组件中

当在父组件中单击带有nextAudio函数的按钮时,我想将_audioState重新分配回“Listen”,但一旦子组件更改此值,输入绑定在父组件中就不起作用

我仍在学习Angular 2,不确定让它工作的最佳方式。我感谢你的建议。我的代码如下

父组件:

 @Component({
    selector: 'parent-component',
    template: ' <div>
                    <button (click)="nextAudio()"></button>
                    <audio-button [audioPath]="_audioPath"  
                    [audioSrc]="_audioCounter" [audioState]="_audioState">          
                    </audio-button>
                </div>',
    styleUrls: ['./parent-component.less']
})

export class ParentComponent {
 _audioPath: string = "../audio/";
 _audioCounter: number = 1;
 _audioState: string = "Listen";

  nextAudio(): void{
    this._audioCounter = this._audioCounter + 1;
    this._audioState = "Listen";
  }  
}
@Component({
    selector: 'audio-button',
    template: '<button (click)="playSound()"><i class="fa fa-volume-up"></i>    
    {{audioState}}</button>',
    styleUrls: ['./audio-button.component.less']
})
export class AudioButtonComponent {
    @Input() audioPath: string;
    @Input() audioSrc: string;
    @Input() audioState: string;

playSound(): void {
    let sound: any = new Audio(this.audioPath + this.audioSrc + ".mp3");
    sound.play();
    this.audioState = "Playing";
    sound.addEventListener('ended', () => {
        this.audioState = "Replay";
    }, false)

    event.preventDefault();
   }
}
@组件({
选择器:“父组件”,
模板:'
',
样式URL:['./父组件.less']
})
导出类ParentComponent{
_audioPath:string=“../audio/”;
_音频计数器:数字=1;
_audioState:string=“Listen”;
nextAudio():void{
这个。_audioCounter=这个。_audioCounter+1;
这是。_audioState=“Listen”;
}  
}
子组件:

 @Component({
    selector: 'parent-component',
    template: ' <div>
                    <button (click)="nextAudio()"></button>
                    <audio-button [audioPath]="_audioPath"  
                    [audioSrc]="_audioCounter" [audioState]="_audioState">          
                    </audio-button>
                </div>',
    styleUrls: ['./parent-component.less']
})

export class ParentComponent {
 _audioPath: string = "../audio/";
 _audioCounter: number = 1;
 _audioState: string = "Listen";

  nextAudio(): void{
    this._audioCounter = this._audioCounter + 1;
    this._audioState = "Listen";
  }  
}
@Component({
    selector: 'audio-button',
    template: '<button (click)="playSound()"><i class="fa fa-volume-up"></i>    
    {{audioState}}</button>',
    styleUrls: ['./audio-button.component.less']
})
export class AudioButtonComponent {
    @Input() audioPath: string;
    @Input() audioSrc: string;
    @Input() audioState: string;

playSound(): void {
    let sound: any = new Audio(this.audioPath + this.audioSrc + ".mp3");
    sound.play();
    this.audioState = "Playing";
    sound.addEventListener('ended', () => {
        this.audioState = "Replay";
    }, false)

    event.preventDefault();
   }
}
@组件({
选择器:“音频按钮”,
模板:'
{{audioState}}},
样式URL:['./音频按钮.component.less']
})
导出类AudioButton组件{
@Input()音频路径:字符串;
@Input()audioSrc:string;
@Input()audioState:字符串;
playSound():void{
让声音:any=新音频(this.audioPath+this.audioSrc+“.mp3”);
声音。播放();
this.audioState=“播放”;
sound.addEventListener('end',()=>{
this.audioState=“Replay”;
},错)
event.preventDefault();
}
}

有几种方法可以做到这一点,包括

1.(建议)使用 参考资料

()

2. 比如说,

@Component({
selector: 'parent-component',
template: `<div>
                Current state : {{_audioState}}
                <hr />
                <audio-button [audioPath]="_audioPath"
                [audioSrc]="_audioCounter" [audioState]="_audioState"
                (emit-status)="updateStatus($event)"
                >
                </audio-button>
            </div>`
})

export class ParentComponent {
  _audioPath: string = "../audio/";
  _audioCounter: number = 1;
  _audioState: string = "Listen";

  nextAudio(): void{ 
    this._audioCounter = this._audioCounter + 1;
    this._audioState = "Listen";
  }

  private updateStatus(status:string){
    this._audioState= status;
  }
}
结果

谢谢!谢谢你的帮助。我以前使用过output和EventEmitter,但不确定是否有更好的方法。我认为状态管理最干净的方法之一是使用ngrx/stroe。然而,在一个不太复杂的应用程序中,我们可以使用EventEmitter或ViewChild来完成它。听起来不错。我正在考虑使用ViewChild,但无法正确引用子组件。ViewChild只能在ngAfterViewInit()中使用,对吗?
export class AudioButtonComponent {
   //...
  @Input() audioState: string;
  playSound(): void {
     //...
     this.audioState = "playing";
  }
}