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

Posted

技术标签:

【中文标题】Angular6 Div 围绕来自同一用户的数组【英文标题】:Angular6 Div around Arrays from same user 【发布时间】:2018-12-23 20:40:54 【问题描述】:

我有一些 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 个人发送垃圾邮件时,我想从最新消息中删除头像。我想删除来自同一个人的 2 条消息之间的空格。像这样:

但由 2 个不同的人编写,它必须是这样的:

我很难弄清楚如何解决这个问题。我所问的只是告诉我,没有很多性能损失是没有办法的。我需要以某种方式执行此操作,仅使用数据directionuser(表示用户名)自动处理所有这些内容,或者我可能为user_id 添加一个字段,然后我有2个必填字段(@987654335 @ 和 user_id ) 我们的目标是让这一切变得尽可能简单和自动,因为这是我希望未来很多人会使用的开源库。我不想强迫他们做太多逻辑的事情。 :)

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

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

【问题讨论】:

我会使用有条件的 CSS 元素来做到这一点,例如:删除消息之间的边距并在每条消息后添加一个“边距”div,并为其添加一个条件类以检查用户是否来自此index和过去的index是一样的,比选小margin class,如果不是选大padding class,和头像一样的东西,如果是同一个用户,不显示。 你能给我举个例子吗?我在这件事上很糟糕......而且你不认为将 div 包裹在来自同一方向和用户的消息周围更好吗?那么我只需要 1 个逻辑条件,其余的可以用简单的 css(第一个和最后一个孩子)来完成,但我以前从未见过有人将 div 实时包裹在元素周围。 (也许真的会破坏性能) 你不能单独在css中做,因为nth:child css不带条件,所以你无法匹配实时用户,如果我回家之前没有人回答,我会尽力为你提供举个简单的例子。 如果你有一个好的模型,结构与你想要生成的视图相匹配,一切都会变得更简单。您的描述表明您不想显示消息列表。您想要显示消息组列表,其中每个组有 1-N 条后续消息,所有消息均由单个用户发布。因此,使用 TypeScript 从您的消息中创建一组消息组(通过检测同一用户发布的后续消息)。然后你可以遍历每个组,并用一个头像显示每个组,并在这个组内,迭代该组的消息。 @JBNizet ,从他的话题和图片来看,他好像在进行某种聊天?因此,如果它是实时聊天,每次新消息到来时都运行这些分组,将占用大量资源。最好不要依赖控制器来执行此操作,因为它仅与视图有关。 【参考方案1】:

一种可能的解决方案是使*ngIf 条件更复杂一些。

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

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

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

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

【讨论】:

这对时间戳有意义,但我如何修改边距和边框半径等其他内容?因为这对我来说是最简单的解决方案,当消息组周围有一个 div 时。但是你认为这是因为性能没有选择吧? 如果我错了,请纠正我,divclass="msg-content" 负责显示包含消息的灰色圆形框。如果是这样,为什么不使用[ngClass]="msg-content: &lt;&lt;condition for NOT showing avatar&gt;&gt;, msg-content2: &lt;&lt;condition for showing avatar&gt;&gt;",其中 msg-content2 是具有不同边框的不同类? 头像在一个 div 中,类 msg-avatarmsg-content 的 div 处于同一 DOM 级别如果无法用 message group div 包装,那么我需要很多元素的条件.在msg-avatar 上隐藏头像(如果不是最后一条消息),在msg-content 上更改边框。 (首先删除边界半径底部,中间 div 删除所有边界半径,最后发布删除顶部边界半径:..)并在带有类 msg 的 div 上更改消息周围的边距......这很多逻辑......一个 div作为消息组工作将使一切变得更容易,因为我可以用 css 做所有事情。 这是一个权衡:要么修改数据结构,使模板更简单,要么保持数据结构简单,使模板复杂化,增加大量逻辑。我的建议是采用@JBNizet 的建议,将来自同一用户的消息分组。但是,我看不出如何区分用户 A 的消息(编号为例如:1、2、3),而另一个用户 B 的消息出现在 A 的第 3 条消息之前。在这种情况下,您需要将时间戳分别对 A 的 [1,2][3] 进行分组。我不确定是否有任何其他方式可以直接用消息组div包装。 您可以在顶部有一个 div,在底部有一个 div,这是具有固定边距的分隔线,如果您上面的同一用户不应用该样式,除此之外,底部相同,只需检查下一条消息。我建议为每条消息创建一个新组件或指令,以更加有序和简单地处理所有这些逻辑。【参考方案2】:

您所追求的可以通过简单地比较 ngFor 循环中的当前 + 下一个消息方向并查看它们是否不同然后添加“最后一个”或任何您想要命名的类来完成。因为您本质上想要“这个方向的最后一个”消息。

<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>
    [class]="message.direction"

这将为我们提供消息的方向作为一个类 meothers 在你的情况下,非常简单。

现在让我解释一下“最后”类部分:

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

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

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

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

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

对于显示/隐藏头像,只要你有 last 类,这只是简单的 css。

这是一个工作示例: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
  "

【讨论】:

非常感谢您的详细解释和令人敬畏的 stackbliz!这帮助我达到了我想要达到的目标。

以上是关于Angular6 Div 围绕来自同一用户的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IBM Worklight 中重定向到同一页面但不同的 div/视图?

如何将请求标头信息传递给 Angular6 应用程序(JWT 通过请求标头发送)

如何在 React 中显示来自 JSON URL 数组的图像

来自同一浏览器的 laravel 和多会话

围绕特定文本换行新的div元素

如何使用 jQuery 显示来自 JSON 的多个数组?