DOM的计算属性,过滤器和更新

时间:2015-10-21 14:33:50

标签: ractivejs

我有一个包含很多元素的计算属性。 根据用户输入,我需要过滤掉它所基于的一些元素。

[
    {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'元素被过滤掉时。

更新了小提琴:http://jsfiddle.net/7kubqbba/4/

1 个答案:

答案 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.observeractive.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 });