我有一个消息流对象,如下所示:
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动画。)
答案 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不会。
它所知道的是我们有一个表达式,其值由messages
和current_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来证明这一点。我希望这是有道理的,如果没有,请告诉我 - 对不起,我没有尽快回答这个问题。