如何附加到knockout foreach中的现有元素而不是创建新元素

时间:2013-07-29 20:33:17

标签: javascript knockout.js ko.observablearray

这是一个小众案例,但我有一个简单的聊天室风格。

因此会有一个可观察的聊天项数组(这可能仅限于100个被分页的条目以保持良好的性能)。

所以目前的foreach看起来像:

<!-- ko foreach: ChatEntries -->
<div class="chat-entry">
    <img class="entry-sender"></span>
    <span class="entry-content" data-bind="html: Content"></span>
</div>
<!-- /ko -->

目前,每个条目都会添加一个新的聊天条目,这很好,看起来像这样:

The existing chat system

然而,如果下一篇文章是由同一个人发布的,那么现在需要附加到现有的聊天条目,如此(原谅可怕的绘画作业)。

The required chat system

而且我不知道如何在淘汰赛中这样做......我在想我可以做一个afterRender并检查它是否与上一个条目海报相同然后删除所有创建的dom并找到上一个条目并使用jquery或其他东西只是附加元素,但这感觉非常黑客,因为我手动操作dom。

那么有没有好的方法来解决这个问题?

==编辑==

只是为了清理一些事情,目前我总是在新条目进入时附加到可观察数组,但是每次出现新内容时都会重新创建数组,因为这会简化事情相当多,但不确定这样做的明显影响与仅追加个别条目。

目前在截止点之后有一个50的缓冲区,所以主阵列存储大约100个然后将允许另外50%(最多150个条目)然后一旦它超过它,它将切断最后50个条目和重新创建数组,因此再次有100个条目,然后用户可以回页查看以前的条目。所以这减少了娱乐,但听起来可能最终变得有点复杂。所有进来的聊天都存储在本地存储中,因此可以快速分页而无需服务器,因此不必担心丢失聊天数据。

2 个答案:

答案 0 :(得分:1)

您可以与if函数一起使用一些淘汰赛$index()

不是最优雅的解决方案,但它很简单,它可以完成任务。

<!-- ko foreach: ChatEntries -->
<div class="chat-entry">
    <!-- ko if: $index() === 0 -->  //first item does not have a previous
        <span class="entry-sender">img</span>
        <span class="entry-content" data-bind="html: Content"></span>
    <!-- /ko -->
    <!-- ko if: $parent.ChatEntries()[$index()-1]-->    //check if previous is same user
        <!-- ko if: user !== ($parent.ChatEntries()[$index()-1].user)-->    
        <span class="entry-sender">img</span>
        <span class="entry-content" data-bind="html: Content"></span>
        <!-- /ko -->
        <!-- ko if: user === ($parent.ChatEntries()[$index()-1].user)-->    
        <span class="entry-content" data-bind="html: Content"></span>
        <!-- /ko -->
    <!-- /ko -->
</div>
<!-- /ko -->

看看小提琴here

这可以通过计算字段完成,但它需要一些javascript代码并且您可以更改模型。此解决方案仅需要更改为html

答案 1 :(得分:1)

不会更改数组以适应您的观点更加黑客行事?对于操纵DOM,敲出有bindingHandlers。也许自定义绑定可能就是你想要的。只需将currentUser与previousUser进行比较,然后决定将span附加到上一个条目或创建一个新条目。没有jQuery,纯粹的javascript。或jQuery,如果你想用新效果到达的效果。您甚至可以将模板作为参数提供,这样您的聊天就可以有供用户选择的主题。

Bindings还提供了很多信息:http://www.knockmeout.net/2011/07/another-look-at-custom-bindings-for.html

IMO这可能是最干净的解决方案,数据在模型中,视图在视图中。你的主要HTML是干净的:

<!-- ko foreach: ChatEntries as chatEntry -->
    <div class="chat-entry" data-bind="yourCustomChatBinding: chatEntry"></div>
<!-- /ko -->

只有一个想法:如果附加数据,上面的代码将创建空div。 KO虚拟元素:

<!-- ko foreach: ChatEntries as chatEntry -->
    <!-- ko yourCustomChatBinding: chatEntry -->
<!-- /ko -->

虚拟元素有一些很好用的API:http://knockoutjs.com/documentation/custom-bindings-for-virtual-elements.html