Angular6 Div 围绕来自同一用户的数组

Angular6 Div around Arrays from same user

我有一些 Messenger 的数据:

public messages = [
    {
        direction: 'me', // Required
        user_id: 554, // Required
        user: 'Sven', // Optional
        avatar: 'urltoavatar', // Optional
        message: 'Hi du alter babbsack!' // Optional
    },
    {
        direction: 'others', // Required
        user_id: 8774, // Required
        user: 'Hannes', // Optional
        avatar: 'urltoavatar', // Optional
        message: 'Hey whats going on?' // Optional
    },
    {
        direction: 'others', // Required
        user_id: 8774, // Required
        user: 'Hannes', // Optional
        avatar: 'urltoavatar', // Optional
        message: 'No Idea bro! This ' // Optional
    }
];

我将其插入 Messenger 消息区:<mark6-messenger-message [messages]="messages" [avatarMe]="false" [avatarOthers]="true"></mark6-messenger-message>

<mark6-messenger-message> 的观点:

<ng-container *ngFor="let message of messages">
    <div class="msg" [ngClass]="message.direction">
        <div class="msg-avatar" *ngIf="(avatarMe && message.direction === 'me') || (avatarOthers && message.direction === 'others')">
            <img [src]="message.avatar" [alt]="message.user">
        </div>
        <div class="msg-content">
            <div class="msg-message">{{message.message}}</div>
        </div>
    </div>
</ng-container>

在浏览器中的结果是这样的:(我更改了代码中的消息,不用担心这个)

现在的问题是,当1 Person Spam some messages时,我想从最新消息中删除头像。我想删除来自同一个人的 2 条消息之间的 space。像这样:

但是两个不同的人写的一定是这样的:

我很难弄清楚如何解决这个问题。我所要求的只是告诉我,没有失去很多性能是没有办法的。我需要以某种方式执行此操作,仅使用数据 directionuser(这意味着用户名)自动处理所有这些东西,或者我可能为 user_id 添加一个字段然后我有2 个必填字段(directionuser_id) 目标是尽可能简单和自动地完成此操作,因为这是针对开源库的,我希望将来会有很多人使用。我不想强迫他们做太多逻辑上的事情。 :)

如果您需要检查其他文件或更多信息,这里是存储库:https://github.com/DevMonkeysDE/ngx-mark6/tree/master/projects/mark6-lib/src/lib/messenger

最好的事情是当每个人的每包消息都得到一个 div 容器时,我就可以简单地使用 css:first-child 和 css:last-child。但是它必须在整个过程中即时转换每条消息 HTML DOM,这可能真的非常非常破坏性能。

一个可能的解决方案是使 *ngIf 条件稍微复杂一些。

修改 *ngFor 指令以跟踪消息索引,如下所示:*ngFor="let message of messages; let i=index"

然后您可以尝试 *ngIf="(avatarMe && message.direction === 'me' && (messages[i+1].direction !== 'me') || (avatarOthers && message.direction === 'others' && (messages[i+1].user_id !== message.user_id))" 之类的方法,仅当下一条消息不是来自同一用户时才显示头像

但是,它可能对最后一条消息不起作用,因为它找不到 messages[i+1]

另一个解决方案是,如果可能的话,修改 messages 数组的数据结构以包含 timestamp(因为它是一个消息传递应用程序,所以跟踪时间更有意义)。然后我们可以按时间戳排序,并显示带有最大时间戳的消息的头像。

你想要的可以通过简单地比较 ngFor 循环中的当前+下一条消息方向并查看它们是否不同然后添加一个 "last" 或任何你想命名的东西来完成 class .因为您本质上想要 "last of this direction" 消息。

<div [class]="message.direction" [ngClass]="{last: messages[i+1] && messages[i+1].direction !== message.direction || isLast, message:true}"
 *ngFor="let message of messages; let isLast = last; let i = index;">
    {{message.message}}
</div>
  1. [class]="message.direction"

这将为我们提供消息的方向,在您的情况下是 class meothers,非常简单。

现在让我解释一下 "last" class 部分:

  1. *ngFor="let message of messages; let isLast = last; let i = index;"

ngFor 指令公开了一些局部变量,如 lastfirst,index,因此我们可以利用这一点并将我们的 isLast 变量分配给 last 来自 ngFor 循环的局部变量,同时我们的 i 变量将保存当前的 index ngFoor 循环。 Docs for ngFor

  1. [ngClass]="{last: messages[i+1] && messages[i+1].direction !== message.direction || isLast, message:true}

如果我们的条件为真,我们使用 ngClass 指令应用 last class,在这种情况下,条件只是比较循环中的下一条消息 (messages[i+1].direction) 是否为与循环 message.direction 中的当前消息不同。唯一的问题是循环 messages[i+1] 中的最后一条消息将是 undefined,这就是 or || isLast 检查通过的地方,因为这对于最后一条消息始终为真循环。 Docs for ngClass

顺便说一句,messages[i+1] && messages[i+1].direction 你需要这样做,这样你只有在定义了 messages[i+1] 的情况下才会短路你的条件检查方向,否则你的代码将在最后一项上崩溃。 You can read more about that in the Javascript docs

对于 showing/hiding 头像,这很简单 css 一旦你有 last class。

这是一个工作示例:https://stackblitz.com/edit/angular-gwqqee

希望对您有所帮助。

编辑:我忘了你有两个以上的用户,但同样的概念适用,只需检查 user_id 而不是方向,请参阅更新的示例。

[ngClass]="{
  'message': true,
  'last-from-direction': messages[i+1] && messages[i+1].direction !== message.direction || isLast,
  'last-from-user': messages[i+1] && messages[i+1].user_id !== message.user_id || isLast
  }"