计算 属性、过滤并更新 DOM
Computed property, filters and updates to DOM
我有一个包含很多元素的计算 属性。
根据用户输入,我需要过滤掉它所基于的一些元素。
[
{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 上执行,触发不需要的转换。
一个fiddle顶一千字: http://jsfiddle.net/7kubqbba/4/ (edited, see old version)
如果单击切换按钮,您会注意到在左侧的计算元素上执行了转换。
我相信这是因为 Ractive 没有更新整个 <li>....</li>
标签,而是只更新了应该受影响的特定部分。在这种特定情况下:名称和 class.
<li class="animateme animateme-{{display}}">{{name}}</li>
我想做的是:
- 继续使用计算属性
- 根据数据变化重建整个
<li>
(基本上,放弃一些 Ractive 的效率)
关于如何做到这一点的任何提示?
(我完全有可能以错误的方式处理这个问题,如果是这样,请告诉我)
编辑:
tl;dr. 视觉转换应该在任何 'display' 属性 被修改时触发(即 ),而不是 'display:false'正在过滤掉元素。
已更新 fiddle:http://jsfiddle.net/7kubqbba/4/
参见 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 不会跟踪不同数组中相同对象引用之间的变化(除非使用魔术模式),这是 "hidden" 通过重新计算 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
) 中,您可能会使用 link 方法。
编辑:我想到的另一种选择是在过滤器更改时禁用转换。见 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 });
我有一个包含很多元素的计算 属性。 根据用户输入,我需要过滤掉它所基于的一些元素。
[
{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 上执行,触发不需要的转换。
一个fiddle顶一千字: http://jsfiddle.net/7kubqbba/4/ (edited, see old version)
如果单击切换按钮,您会注意到在左侧的计算元素上执行了转换。
我相信这是因为 Ractive 没有更新整个 <li>....</li>
标签,而是只更新了应该受影响的特定部分。在这种特定情况下:名称和 class.
<li class="animateme animateme-{{display}}">{{name}}</li>
我想做的是:
- 继续使用计算属性
- 根据数据变化重建整个
<li>
(基本上,放弃一些 Ractive 的效率)
关于如何做到这一点的任何提示?
(我完全有可能以错误的方式处理这个问题,如果是这样,请告诉我)
编辑:
tl;dr. 视觉转换应该在任何 'display' 属性 被修改时触发(即 ),而不是 'display:false'正在过滤掉元素。
已更新 fiddle:http://jsfiddle.net/7kubqbba/4/
参见 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 不会跟踪不同数组中相同对象引用之间的变化(除非使用魔术模式),这是 "hidden" 通过重新计算 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
) 中,您可能会使用 link 方法。
编辑:我想到的另一种选择是在过滤器更改时禁用转换。见 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 });