【问题标题】:Typescript Parent/Child打字稿父母/孩子
【发布时间】:2017-06-13 02:02:50
【问题描述】:

Angular2/Typescript - 父/子指令(?)

我是 Angular2/Typescript/javascript 的新手,而且还在学习。结果,我不完全确定如何为我的问题命名。我的应用程序的基础是纸牌游戏。前提(相对于我的挣扎)是游戏有 2 个玩家,每个玩家有 5 张牌。我有 API 调用来构建/归还手牌。

在我的 app.component 模板中,我有 2 个 div 块;每个玩家的手牌一张。目前,我通过构建两个不同的卡片数组(名为 p1cards 和 p2cards)来实现它。以下是相关代码:

<div class="player1Cards" id="player1Cards">
  <ul class="list-group">
    <div draggable *ngFor="let card of p1cards" [dragData]="card" 
class="list-group-item">
      <img src="{{cardBluePath + card.fileName}}">
    </div>
  </ul>
</div>

<div class="player2Cards" id="player2Cards">
  <ul class="list-group">
    <div draggable *ngFor="let card of p2cards" [dragData]="card" 
class="list-group-item">
      <img src="{{cardBluePath + card.fileName}}">
    </div>
  </ul>
</div>

这里是整个 AppComponent 的实际导出类:

@Injectable()
export class AppComponent implements OnInit
{
  @ViewChild(ModalComponent) errorMsg: ModalComponent;

  errorMessage: string;
  gameBoard: GameBoard[];
  name: {};
  mode = 'Observable';

  //we need a gameboard (maybe not)

  //we need an array of players
  player:Player;
  players:Player[] = [];

  p1cards:Card[] = [];
  p2cards:Card[] = [];
  droppedItems = [];

  //This tells us where the card images can be found
  cardBluePath = "/assets/deck/Blue/";
  cardRedPath = "/assets/deck/Red/";

  //The boardService will handle our API calls
  boardService;

  //Initialize the API service
  constructor(boardService:BoardService) {
    this.boardService = boardService;
  }


  //On load...
  ngOnInit()
  {
    //Create the game
    this.boardService.createGame()
        .subscribe(
         error =>  this.errorMessage = <any>error);

   //Create the players
   this.createPlayer(0);
   this.createPlayer(1);
 }


  createPlayer(player: number)
  {
    var playerName;
    if (player == 0) {playerName = "Player1"} else {playerName = "Player2"};

    //We'll make a call to the API to build the hand of cards
    this.boardService.buildHand(player)
        .subscribe(
         cardList =>
         {
           var cardData = [];
           cardData = JSON.parse(cardList.toString());

           var i, itemLength, card
           itemLength = cardData.length;
           for(i=0;i<itemLength;i++)
           {
             let card = new Card();
             Object.assign(card,
             {
               "cardNum":i,
               "id": cardData[i].id,
               "displayName": cardData[i].displayName,
               "fileName": cardData[i].fileName,
               "left": cardData[i].left,
               "top": cardData[i].top,
               "right": cardData[i].right,
               "bottom": cardData[i].bottom,
               "level": cardData[i].level,
               "native": cardData[i].native
             });

             if (player == 0) {this.p1cards.push(card)} else {this.p2cards.push(card)};
             ////this.cards.push(card);
           }

           //Now we will create the player and feed it the hand
           this.player = new Player(playerName);
           if (player ==0) {this.player.cardHand = this.p1cards} else {this.player.cardHand = this.p2cards};
           this.players.push(this.player);
         }
       );
  }


  //When a card is dropped...
  onItemDrop(e: any, slot: any)
  {
      e.dragData.slot = slot;

      //Update the object
      this.boardService.playCard(slot, e.dragData.card)
          .subscribe(result => {
            //If the slot is open and the card is played, physically move the item
            if (result == "true" )
            {
              this.droppedItems.push(e.dragData);
              this.removeItem(e.dragData, this.p1cards);
            }
            else{
              window.alert("Slot already occupied.");
              //this.modalWindow.show()
              //this.errorMsg.showErrorMessage("Slot already occupied.");
              //this.errorMsg.show();
            }
          });
  }


  //Remove the card from the hand
  removeItem(item: any, list: Array<any>)
  {
      let index = list.map((e) => {
          return e.cardNum
      }).indexOf(item.cardNum);
      list.splice(index, 1);
  }
}

createPlayer 函数实际上是问题的开始。目前,它将进行 API 调用并将 JSON 解析回卡片数组。现在,卡片数组本地存在于 AppComponent 中(作为 p1cards 或 p2cards)。

我想做的是为每个玩家创建一个玩家对象(组件),分配他们各自的手牌,然后将这些玩家放入一个数组中。我让那部分工作(部分代码仍然存在于上面,但不是全部),但我在 *ngFor 中撞墙以显示卡片。在伪代码中,我明白我需要做什么,但在实践中我无法弄清楚。

我知道 div 类 player1Cards 需要类似于“let player of Players where name = player1”,然后我需要遍历 player.cardHand[] 数组以显示每张牌。我尝试了很多东西,但没有任何效果。

然后,经过几个小时的 Google 搜索,我得出结论,我需要一个子视图供玩家处理它。我目前有以下内容:

我的 player.html 是:

<div draggable *ngFor="let card of cardHand" [dragData]="card" class="list-group-item">
  <img src="{{cardBluePath + card.fileName}}">
</div>

而我的 player.ts 是:

import { Component, Input, OnInit } from '@angular/core';
import { Card } from './card';


@Component({
    selector: 'player',
    templateUrl: './player.html',
})

export class Player implements OnInit
{
  public cardHand: Card[];
  cardBluePath = "/assets/deck/Blue/";

  constructor
  (
    public name: string
  )
  {}

  ngOnInit()
  {

  }
}

然后在我的 AppComponent 模板中,我添加了块(并导入了 player.ts)

我在 App.Component 上收到一条错误消息“内联模板:69:16 原因:没有 String 的提供者!”。在我执行的所有 Google 研究和我尝试的所有更改(ViewChild、输入/输出、参考)中,我无法让它发挥作用。我不记得我到底做了什么,但有一次我能够消除错误,但卡片数组没有传递给玩家(我希望我已经提交或隐藏了该代码)。

在我看来,我理解手头的任务,但我无法实现它。我知道我需要创建 Player 对象并将其提供给相应的 cardHand 以便播放器 html 能够解析它。我可以在 AppComponent 中很好地做到这一点,但是一旦我尝试作为父母/孩子做到这一点,我就会卡住。

有人可以帮助我朝着正确的方向前进吗?

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    我知道我需要创建 Player 对象并将其提供给相应的 cardHand 以便播放器 html 能够解析它。我可以 在 AppComponent 中很好,但是一旦我尝试作为父母/孩子这样做, 我卡住了。

    我同意创建玩家对象数组是有意义的,每个玩家对象手中都有一组卡片。像这样的:

    let player1 = {name:'Player 1',hand:[]} 
    let player2 = {name:'Player 2',hand:[]}
    this.players = [player1, player2]
    
    player1.hand.push(this.dealCard())
    ...
    
    player2.hand.push(this.dealCard())
    ...
    

    然后您可以创建一个玩家组件来展示玩家(甚至可以创建一个卡片组件来展示他们的手牌)。在您的根模板中,您将遍历玩家,创建您的玩家组件并传入玩家数据,包括他们的手。

    <player-component *ngFor="let player of players" [player]="player"></player-component>
    

    确保您的播放器组件具有接收播放器数据的输入:

    export class PlayerComponent implements OnInit {
     @Input() player: Player;
      constructor() { }
    
      ngOnInit() { }
    }
    

    然后在&lt;player-component&gt;模板中循环玩家的手并渲染卡片:

    <p>I am {{player.name}}. My hand is:</p>
    <ul>
      <li *ngFor="let card of player.hand">{{card}}</li>
    </ul>
    

    这是一个 plunker,展示了一个工作演示,它是此设置的简化版本: https://plnkr.co/edit/5Hz8P7poCb9Ju5IR6MWs?p=preview 您应该能够将其配置为游戏的特定设置。祝你好运!

    【讨论】:

      【解决方案2】:

      在你的播放器组件中,如果你想访问另一个组件: 1. 该组件需要在顶部有一个导入语句 2.在@component部分,你需要将它包含在Providers中 3. 也包含在构造函数中

      欲了解更多信息,请访问:https://angular.io/guide/dependency-injection

      【讨论】:

        猜你喜欢
        • 2016-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 2023-04-06
        • 1970-01-01
        相关资源
        最近更新 更多