如何识别对象数组中链的第一个和最后一个元素

时间:2017-05-20 19:04:12

标签: javascript angular

伙计们,当我试图在聊天中设置适当的课程时,我就堆积了 我有一个包含下一个模板的组件:

...
<ul>
    <li *ngFor="#mes of chatMessages; #index = index;">
        user {{mes.user.id}}:
        <span 
                [class.header-recent]="isRecentHeader(chatMessages, mes, index)"
                [class.is-recent]="isRecent(chatMessages, mes, index)"
                [class.last-recent]="isLastRecent(chatMessages, mes, index)">
            {{mes.text}}
        </span>
    </li>
</ul>
...

我正在尝试将三个不同的类应用于每个消息.header-recent应该应用于来自一个用户的消息链中的第一条消息。对用户在不到60秒内发布的消息的类.is-recent。并.is-last-recent在最近的消息链中发送消息。就像图片一样。

enter image description here

消息数组看起来像

[...
{
    "type": "message",
    "id": "19372",
    "text": "а43а\n",
    "created": 1495026352,
        "user": {
            "id": 2
        }
  },
  {
    "type": "message",
    "id": "19373",
    "text": "safaf",
    "created": 1495026357,
        "user": {
            "id": 1
        }
  },
  {
    "type": "system",
    "id": "19374",
    "text": "SYSTEM MESSAGE",
    "created": 1495027801,
        "user":{
            "id": "SYSTEM"
        }
   }
...]

我需要编写3个函数,每个函数确定一个消息类。我现在有两个

    isRecentHeader(mess, mes, index){
        let lastMessage;
        if( index == mess.length-1){
            lastMessage = mess[index];
        } else if( index => 0 && index != mess.length-1) {
            lastMessage = mess[index-1];
        }
        return lastMessage && !this.calcRecent(mes, lastMessage) && lastMessage.type != 'system';

    }

    isRecent(mess, mes, index){
        let lastMes = mess[index-1];
        return this.calcRecent(mes, lastMes);
    }

    isLastRecent(mess, mes, index){
        // confuse here
    }

    calcRecent(message, lastMessage){
        const messageDate = moment(message.created * 1000);
        const lastMessageDate = lastMessage ? moment(lastMessage.created *1000) : null;

        return lastMessage && (lastMessage.type != 'system')
        && (message.type != 'system')
        && (lastMessage.user.id == message.user.id)
        && ((messageDate.valueOf() - lastMessageDate.valueOf()) / 1000 <= 60)
    }

因此函数isRecent()工作正常,isRecentHeader()几乎可以正常工作,但将.header-recent类应用于单个邮件。并没有工作isLastRecent()功能。 所以我的问题是,如何修改isRecentHeader()中的代码,以便它不会将类应用于单个消息,以及我应该在isLastRecent()函数中做什么。这是我的例子的codepen

P.S。如果我的问题似乎不清楚或让您感到困惑,请告诉我,我会尝试编辑或澄清一切。

4 个答案:

答案 0 :(得分:1)

您可以使用以下基本条件轻松实现

<ul>
    <li *ngFor="#mes of chatMessages; #index = index;">
    user {{mes.user.id}}:
    <span 
            [class.header-recent]="index === 0"
            [class.is-recent]="index > 0 && index < (chatMessages.length + 1)"
            [class.last-recent]="(chatMessages.length) === index+1">
        {{mes.text}}
    </span>
</li>
</ul>

<强> Updated pen

答案 1 :(得分:1)

您可以使用* ng中提供的第一个和最后一个boolen值,如下所示,并使用[ngClass]根据值设置类:

<li *ngFor="#mes of chatMessages; let first = first; let last = last" [ngClass]="{ first: first, last: last }">

答案 2 :(得分:1)

关于你的问题:

单个消息问题:

  1. 为了不向单个邮件添加类,您需要验证下一条邮件是否来自同一用户ID。
  2. 上次发送消息:

    1. 最后一条消息与第一条消息的逻辑相同,只需要验证下一条消息来自不同的用户ID。
    2. 我只是让你的代码工作,虽然可以进行一些重构。

      isRecentHeader(mess, mes, index){
          let lastMessage;
          let nextMessage;
          if( index == mess.length-1){
              lastMessage = mess[index];
          } else if( index >= 0 && index != mess.length-1) {
              lastMessage = mess[index-1];
              if (index < mess.length-1){
                  nextMessage = mess[index+1];
              }
          }
      
          return lastMessage && nextMessage && mes.user.id==nextMessage.user.id && !this.calcRecent(mes, lastMessage) && lastMessage.type != 'system';
      }
      

      Updated CodePen

答案 3 :(得分:0)

感谢我的团队领导,他给了我一个答案。 他使用setter和getter来处理组件中的传入消息。

...
private _messages: any[];
recents = [];

@Input()
set messages(messages: any[]) {
    this._messages = messages;

    this.recents = [];

    for(let i = 0; i < messages.length; i++) {
        const message = messages[i];
        const nextMessage = i == messages.length - 1 ? null : messages[i + 1];
        const prevMessage = i == 0 ? null : messages[i - 1];

        const isRecentWithNext = this.isRecentMessages(message, nextMessage);
        const isRecentWithPrevious = this.isRecentMessages(message, prevMessage);

        if(!isRecentWithPrevious && isRecentWithNext) {
            this.recents[i] = 'first-recent'
        } else if(isRecentWithPrevious && isRecentWithNext) {
            this.recents[i] = 'recent';
        } else if(isRecentWithPrevious && !isRecentWithNext) {
            this.recents[i] = 'last-recent';
        }
    }
}

get messages() {
    return this._messages;
}

isRecentMessage(index) {
    return this.recents[index] == 'recent' || this.recents[index] == 'last-recent';
}

isRecentMessages(message, message2?) {
    return message && message2
    && message.type!='system' && message2.type != 'system'
    && (message.user.id == message2.user.id)
    && (Math.abs((message.created - message2.created)) <= 60)
}

在模板中,现在按照代码

设置类
<li *ngFor="#mes of messages; #index = index;">
    <span [class]="recents[index]>
        {{mes.text}}
    </span>
</li>