ractive数据阵列中的身份

时间:2014-02-02 16:11:54

标签: ractivejs

我有一个消息流对象,如下所示:

ractive.data.messages:

{
    stream_id1: {
        some_stream_metadata: "foo",
        stream: [  
            {id: "someid1", message: "message1"}, 
            {id: "someid2", message: "message2"}
        ]
    },
    stream_id2: {
        some_stream_metadata: "bar",
        stream: [
            {id: "someid3", message: "message3"},
            {id: "someid4", message: "message4"}
        ]
    }
}

main_template:

{{#messages[ current_stream_id ]}}
    {{>render_message_stream}}
{{/messages[ current_stream_id ]}}

render_message_stream:

{{#stream}}
    <div class="stream">
    ...someotherstuff...
        {{>render_message}}
    </div>
{{/stream}}

render_message:

<div class="message">
...someotherstuff...
    {{message}}
</div>

我更改“current_stream_id”以更改呈现的消息流。

在更新时,我更改了消息流的内容,如下所示:

ractive.merge(
    "messages.stream_id1.stream",
    new_message_stream,
    {
        compare: function ( item ) { return item.id; }
    });

我也尝试了compare:true选项而不是函数,结果相同:

Ractive始终认为这两个消息属于同一个DOM元素,即使它们存在于完全不同的消息流中:

ractive.data.messages[ "stream_id1" ].stream[1].message
ractive.data.messages[ "stream_id2" ].stream[1].message

问题:

  • 当有介绍/ outro动画时,ractive动画总是只是消息流的结尾,即使在流中间的消息被删除时,我需要帮助让ractive了解哪些消息是相同的。< / p>

  • 当我更改current_stream_id时,ractive不会重新呈现完整的{{&gt; render_message_stream}}部分,而是进入现有的dom并更改所有现有消息中的{{message}}字段,尽管这可能对于dom元素重用很有用,这会触发许多错误的动画。 (例如,如果stream1有一条消息多于stream2,它会触发流中最后一条消息的intro / outro动画。)

1 个答案:

答案 0 :(得分:2)

其中一个问题有一个直截了当的答案;不幸的是,另一个没有。

我将从简单的开始 - 事实

ractive.data.messages[ "stream_id1" ].stream[1].message
ractive.data.messages[ "stream_id2" ].stream[1].message

属于同一个DOM元素。你是正确的,因为Ractive更新现有元素而不是删除它们并创建新元素 - 这是其设计的核心部分。在这种情况下,这是不受欢迎的行为,但您可以这样解决:

// instead of immediately switching to a new stream ID like this...
ractive.set( 'current_stream_id', 'stream_id2' );

// you can set it to a non-existent ID. That will cause the existing DOM
// to be removed. When you set it to an ID that *does* exist, new DOM
// will be created:
ractive.set( 'current_stream_id', null );
ractive.set( 'current_stream_id', 'stream_id2' );

// or, if you'd like the initial transitions to complete first...
ractive.set( 'current_stream_id', null ).then(function () {
  ractive.set( 'current_stream_id', 'stream_id2' );
});

另一个问题 - merge()没有合并,而是表现得好像你正在做ractive.set('messages.stream_id1.stream', new_message_stream) - 更难。问题是,当您和我知道{{#messages[ current_stream_id ]}}messages.stream_id1时等同于current_stream_id === 'stream_id1,而 Ractive不会

它所知道的是我们有一个表达式,其值由messagescurrent_stream_id决定。当其中任何一个引用的值发生更改时,将重新计算表达式,如果 值发生更改,则DOM将更新 - 但使用标准set()。执行ractive.merge('messages.stream_id1.stream', ...)时,Ractive会更新依赖于messages.stream_id1.stream的“上游”或“下游”的关键路径的所有内容 - 包括messages。这就是表达式如何知道它需要重新评估。

未来的Ractive版本有可能以更智能的方式处理这种情况。也许它可以记录受合并操作影响的数组,并检查评估程序结果以查看它们是否与其中一个数组相同,如果是,则使用merge()而不是set()。也许它可以以某种方式分析函数,以查看{{#messages[ current_stream_id ]}}部分是否应该将messages.stream_id1的依赖注册为current_stream_id === 'stream_id1',而不是内部生成的{{1} keypath。

但同时这些对你没有任何帮助。在当前情况下使用${messages-current_stream_id-}的唯一方法是使用不使用表达式的单独引用,以及使用模式观察者的一些魔法:

<强> main_template:

merge()

<强> render_message_stream:

{{#current_messages}} <!-- rather than `messages[ current_stream_id ]` -->
    {{>render_message_stream}}
{{/current_messages}}

<强>码

{{#current_message_stream}} <!-- rather than `stream` -->
    <div class="stream">
        {{>render_message}}
    </div>
{{/current_message_stream}}

我已经设置了JSFiddle来证明这一点。我希望这是有道理的,如果没有,请告诉我 - 对不起,我没有尽快回答这个问题。