【问题标题】:View Does Not Change After Model Update模型更新后视图不变
【发布时间】:2016-10-26 00:13:59
【问题描述】:

我正在处理一个足球项目,当我更新服务模型时会遇到问题。我有两个组件(AvailablePlayers 和 SelectedPlayers)和两个服务(AvailablePlayersService 和 SelectedPlayersService)。

可用球员组件列出了用户可以在其中建立自定义球队的所有可用球员。 (想想梦幻足球)选定的球员组件列出了用户从可用球员中选择的所有球员。这两个服务都只有一个硬编码模型,因此我可以使用它进行测试。

我的问题是,当我单击可用播放器组件中的添加按钮以添加到 SelectedPlayersService 模型时,我希望所选播放器组件中的视图能够更新,但没有任何反应。我的列表已正确填充,因此我知道服务已正确注入组件。

我的猜测是我需要以某种方式观察模型,但我不确定 Angular 2 是否具有这种能力。

available-players.component

@Component({
    selector: 'app-available-players',
    templateUrl: './available-players.component.html',
    providers: [AvailablePlayersService, SelectedPlayersService]
})

export class AvailablePlayersComponent {
    public _availablePlayers;
    public _selectedPlayers;

    selectPlayer = (data) => {
        _selectedPlayers.addSelectedPlayer(data); // using running backs for testing AND I feel this is the problem
    }

    constructor(availablePlayers:AvailablePlayersService, selectedPlayers:SelectedPlayersService) {
        this._availablePlayers = availablePlayers.getAvailablePlayers(); // get the available players model
        this._selectedPlayers = selectedPlayers._selectedPlayersModel; // get the selected players model so I can add players to it
    }
} 

available-players.component html

<div class="player-card" *ngFor="let player of _availablePlayers; let i = index">
    <div class="playa-data">
        <span class="player-name">{{ player.name }}</span>
        <i class="fa fa-plus" (click)="selectPlayer(i, player);$event.stopPropagation()"></i>
    </div>
</div>

selected-players.service

@Injectable()
export class SelectedPlayersService {

    public _selectedPlayersModel;

    public addSelectedPlayer = (data) => {
        this._selectedPlayersModel.runningBacks.push(data);
    }

    constructor() {
        this._selectedPlayersModel = [
            runningBacks: [{
                id: 2, 
                imageUrl: '423.png', 
                name: 'Player Bob', 
                position: 'RB',
            }],
        ];
    };
}

selected-players.component

@Component({
    selector: 'app-selected-players',
    templateUrl: './selected-players.component.html',
    providers: [SelectedPlayersService]
})

export class SelectedPlayersComponent {
    private _selectedPlayers;

    constructor(private selectedPlayers: SelectedPlayersService) {
        this._selectedPlayers = selectedPlayers._selectedPlayersModel;
    }
}

selected-players.component html

<div class="position-card">
    <span>Running Backs</span>
    <div *ngFor="let player of _selectedPlayers.runningBacks">
        <span class="player-name">{{ player.name }}</span>
    </div>
</div>

【问题讨论】:

    标签: angular angular2-template angular2-services


    【解决方案1】:

    您在两个组件装饰器中都注入了提供程序。这会给你两个不同的副本,这不是你想要的。你应该只注入一次服务,在树的某个更高的地方,例如在你的 AppComponent 中,如果你有的话。

    此外,您的服务应将其数据公开为Observables。这样您就可以监听数据的变化。

    像这样:

    @Injectable()
    export class SelectedPlayersService {
    
        private _selectedPlayers;
        public selectedPlayers$; //behaviour subject observable
    
        public addSelectedPlayer = (data) => {
            this._selectedPlayers.runningBacks.push(data);
            this.selectedPlayers$.next(
                Object.assign({}, this._selectedPlayers)
            );
        }
    
        constructor() {
            this._selectedPlayers = {
                runningBacks: [{
                    id: 2, 
                    imageUrl: '423.png', 
                    name: 'Player Bob', 
                    position: 'RB',
                }],
            };
            this.selectedPlayers$ = new BehaviourSubject(
                Object.assign({}, this._selectedPlayers)
            );
        };
    }
    

    然后你的组件可以像这样订阅:

    @Component({
        selector: 'app-selected-players',
        templateUrl: './selected-players.component.html',
        providers: [SelectedPlayersService]
    })
    export class SelectedPlayersComponent {
        private _selectedPlayers;
    
        constructor(private selectedPlayers: SelectedPlayersService) {
            this.selectedPlayers.selectedPlayers$.subscribe(
                players => this._selectedPlayer = players
            );
        }
    }
    

    当然,您必须导入 BehaviourSubject,例如 import { BehaviourSubject } from 'rxjs/BehaviourSubject';

    【讨论】:

    • 非常酷,从来没有想过像在 app.component 中那样将它注入更高的位置。我现在要实施它,我会回来的。感谢您的宝贵时间!
    • 快速提问,如果我在app.component 中注入SelectedPlayersService,我还需要将它注入available-players.componentselected-player.component 吗?
    • 刚刚实施了您的建议,我似乎无法理解。我没有收到任何错误,当我console.log() selectedPlayers 时,我可以看到数组已被推送。添加选定的播放器时,视图不会更新。
    • 订阅回调触发了吗?除了应用程序组件之外,您是否在所有地方都删除了服务注入?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 2018-04-02
    • 1970-01-01
    相关资源
    最近更新 更多