使用 Angular CLI 在组件之间处理数据时遇到问题

Posted

技术标签:

【中文标题】使用 Angular CLI 在组件之间处理数据时遇到问题【英文标题】:Having trouble working with data from component to component with Angular CLI 【发布时间】:2019-08-22 04:09:19 【问题描述】:

主要问题与我试图让一个组件与另一个组件交互这一事实有关。我有一个歌曲列表,想法是当点击一首歌曲时,它会调用“正在播放栏”组件中的一个函数。

只需点击播放/暂停按钮即可调用playPause 函数,效果很好。当您单击“播放列表”组件上的一首歌曲并调用“现在播放栏”组件中的函数playSong 时,问题就出现了。该功能本身似乎工作正常,歌曲开始播放并且数据值似乎已分配。但是会出现两个错误。

错误 1: html 不会更新以显示新的标题和艺术家。

错误 2: 当单击播放/暂停以暂停从“播放列表”组件播放的歌曲时,playPause 函数正确输出 this 及其所有正确的数据字段,但为 this.playing 输出 undefined

代码被缩写以便于阅读

now-playing-bar.component.html

<div class="song">currentSong.title</div>
<div class="artist">currentSong.artist</div>

now-playing-bar.component.ts

export class NowPlayingBarComponent implements OnInit 
    isActive: boolean;
    progress: number = 10;
    playing: boolean;
    currentSong: Song = 
        "id": null,
        "title": "",
        "artist": "",
        "length": "",
        "fileName": ""
    ;
    song: any;
    songs: Song[] = [];

    constructor(private songService : SongsService)  

    ngOnInit() 
        this.songService.fetchData()
            .subscribe(d => this.songs = d as Song[]);
    

    playPause() 
        console.log('Play Pause this:');
        console.log(this);
        console.log(this.playing);
        if (this.playing) 
            console.log('Its playing');
            this.playing = false;
            this.song.pause();
        
        else 
            if (!this.song) 
                this.song = new Howl(
                    src: ['assets/music/' + this.songs[0].fileName]
                );
            
            this.currentSong = this.songs[0];
            this.playing = true;
            this.song.play();
        
    

    playSong(id: number) 
        let that = this;
        this.songService.fetchData()
            .subscribe(function(d) 
                if (that.playing) 
                    that.song.stop();
                    that.song.unload();
                
                that.song = new Howl(
                    src: ['assets/music/' + d[id].fileName]
                );
                console.log(that.song)
                console.log(that)
                that.currentSong = d[id];
                that.playing = true;
                that.song.play();
            );
    

playlist.component.ts

import  Component, OnInit  from '@angular/core';
import Song from "../models/Song"
import  SongsService  from "../songs.service";
import  NowPlayingBarComponent  from "../now-playing-bar/now-playing-bar.component"

export class PlaylistComponent implements OnInit 
    songs: Song[] = [];

    constructor(private songService : SongsService, private NP : NowPlayingBarComponent)  

    ngOnInit() 
        this.songService.fetchData()
            .subscribe(d => this.songs = d as Song[]);
    

    songClicked(id) 
        this.NP.playSong(id)
    

如果有帮助的话,我很乐意上传完整的代码,只是不想把它弄得一团糟。我花了几个小时研究试图弄清楚这一点,但我似乎无法理解。我最好的猜测是“播放列表”组件与“正在播放的栏”交互的方式不正确。

【问题讨论】:

将一个组件注入到另一个组件中并不是一个好的做法,而且根本不提倡。您应该使用 Input/Output 在父/子组件之间进行通信。在这种情况下,NowPlayingBarComponent 应该通过输入接受 songId,并在每次更改时对其进行操作。 我会试一试,谢谢 也许我只是不明白,但我没有运气输入。我尝试创建一个音乐服务并将功能移到那里。所以现在音乐服务有歌曲、歌曲[]、播放等数据以及 init() 和 playpause() 等函数。说问题。如果我调用 musicservice.init() 然后调用 musicservice.playpause(),playpause 看不到 init() 对它们所做的变量的任何更改。这些是否也需要添加输入? 【参考方案1】:

已经实现了一个工作示例@https://stackblitz.com/edit/component-to-component。

根据您的示例,它使用两个组件 PlaylistNowPlayingNavbar。我还添加了一个模拟的SongService 来模拟fetchData 方法。

注意:避免从嵌套的子组件调用服务。

看看 UI 开发中的 Presentation vs Container 组件模式。

【讨论】:

以上是关于使用 Angular CLI 在组件之间处理数据时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

vue-cli 组件之间的通信

如何在Angular中的路由组件之间传递数据

Angular 组件之间的通信

如何使用 Angular CLI 在特定文件夹中生成组件?

在组件之间添加数据 Angular

使用 Angular-CLI 创建组件并将其添加到特定模块