我有一个包含很多元素的计算属性。 根据用户输入,我需要过滤掉它所基于的一些元素。
[
{name:'hal', display: false},
{name:'john', display: true },
{name:'jack', display: false},
{name:'george', display: true },
{name:'tom', display: false},
{name:'rick', display: false},
{name:'paul', display: true },
{name:'ringo', display: true },
]
在我的示例中,我希望能够随意过滤掉display:false
的元素。
由于Ractive对数据更改的反应效率很高,因此只对DOM执行特定更改,从而触发不必要的转换。
小提琴胜过千言万语: http://jsfiddle.net/7kubqbba/4/(已编辑,see old version)
如果单击切换按钮,您会注意到左侧的计算元素将执行转换。
我认为这是因为Ractive而不是更新整个<li>....</li>
标记,只会更新应受影响的特定部分。在这个特定的情况下:名称和类。
<li class="animateme animateme-{{display}}">{{name}}</li>
我想做的是:
<li>
数据更改(基本上,放弃一些Ractive的效率)关于我如何做到这一点的任何提示?
(我完全有可能以错误的方式处理这个问题,如果是这样,请告诉我)
编辑:
tl; dr。视觉转换应该在任何'display'属性被修改时触发(即),而不是在'display:false'元素被过滤掉时。
答案 0 :(得分:1)
有关以下示例,请参阅http://jsfiddle.net/7kubqbba/5/。
我实际上认为内联过滤的示例是更好的方法,如果它变得复杂,您可以将逻辑移动到函数中:
{{#if show(this) }} ... {{/if}}
...
data: {
show ( item ) {
const active = this.get( 'active' );
return active !== true || item.display;
}
}
否则,您需要使用ractive.observe
和ractive.merge
来实现与计算属性相同的效果,但需要具有身份识别DOM节点语义:
this.observe('active', active => {
const entries = this.get('entries');
const merge = active ? entries.filter( entry => entry.display ) : entries;
this.merge( 'filtered', merge );
});
请注意,这突出了ractive不跟踪不同数组中相同对象引用之间的更改(除非使用魔术模式),事实&#34;隐藏&#34;通过重新计算原始示例中每次数据更改时发生的filteredElements
。
如果您需要此行为,可以设置观察者在数组之间进行映射:
this.observe('filtered.*.display', ( display, o, k, index ) => {
this.update('entries.'+index+'.display' );
});
this.observe('entries.*.display', ( display, o, k, index ) => {
this.update('filtered.'+index+'.display' );
});
或者在ractive(0.8
)的下一版本中,您可以使用链接方法。
编辑:我想到的另一个选项是在过滤器更改时禁用转换。见http://jsfiddle.net/7kubqbba/6/:
<li on-click="changeDisplay:{{i}},{{display}}" class="animateme animateme-{{display}} {{#if noTransition}}noTransition{{/if}}">{{name}}</li>
// in component:
self.observe('filteredElements', (n, o) => {
if ( n!==o ) {
this.set( 'noTransition', true );
}
})
self.observe('filteredElements', (n, o) => {
setTimeout( () => this.set( 'noTransition', false ) );
}, { defer: true });