如何不在 Mithril 中重新渲染整个列表
How to not re-render the whole list in Mithril
我已经使用 React 一段时间了,想尝试一下 Mithril.js。
浏览了文档和示例并喜欢我所看到的内容,所以我说我应该亲自动手并开始编码!
我有一个 smiple API 调用,它接收 JSON 数据,然后输出包含所有项目的 ul
列表。我已经为动画集成了 GSAP TweenMax,我想要实现的目标非常简单——我在加载时淡入所有内容,然后 onclick
我想淡出一个元素并将其从 [=26] 中删除=]/数据。
似乎正在发生的事情是该元素正在淡出,正在重新呈现整个 ul
列表并且该元素保留在 DOM 中且不透明度为 0:
var Item = {
list: function() {
return m.request({method: 'GET', url: '/api/items'});
}
}
var dm = {
controller: function(data) {
var items = Item.list();
return {
items: items,
remove: function(item) {
items().data.splice(items().data.indexOf(item), 1);
}
}
},
view: function(ctrl) {
return m('ul', [
ctrl.items().data.map(function(item, id){
return m('li',{
key: id,
config: fadesIn,
onclick: fadeOut(ctrl.remove.bind(this, item))
}, item.title);
})
]);
}
}
var fadesIn = function(element){
var tl = new TimelineMax();
tl.from(element, .5, {opacity: 0});
}
var fadeOut = function(callback) {
return function(e) {
m.redraw.strategy('none');
TweenMax.to(e.target, .5, {opacity: 0, onComplete: function() {
m.startComputation();
callback();
m.endComputation();
}});
}
}
m.mount(document.getElementById('test'), dm);
我很新..昨天才开始阅读。
让动画库与 Mithril 一起工作可能很棘手。当库操纵 DOM 状态时,与 Mithril 状态的同步可能会中断。
幸运的是,情况并非如此:您缺少的是配置函数的 isInitialized
参数,它仅在第一次调用时为 false。对此进行测试使淡入只发生一次:
var fadesIn = function(element, isInit){
if(isInit) return;
var tl = new TimelineMax();
tl.from(element, .5, {opacity: 0});
}
在这个简单的例子中重绘也可以被简化,我做了一个fiddle有一个工作的例子:
http://jsfiddle.net/ciscoheat/dkyc0ryc/
因为没有 DOM 操作,调用 m.redraw
就足以从 DOM 中删除 div,但您使用 [= 可能是正确的13=] 当事情变得更复杂时。我什至会将 m.startComputation
移动到 TweenMax.to
调用上方以使其更加安全,但如果同时发生许多其他事情,则可能会阻止其他重绘。你必须找到一个平衡点。 :)
我认为在任何情况下都不需要调用 m.redraw.strategy
。它主要用于当你不想发生任何事情时(也同步),但是异步动画正在启动,所以它不会有任何效果。
编辑:又发现一个问题,key
不能设置为map函数的索引,那么当一个item被移除时它会改变,搞砸了重绘。我已将 fiddle 更新为使用 item.title
作为键。
我已经使用 React 一段时间了,想尝试一下 Mithril.js。
浏览了文档和示例并喜欢我所看到的内容,所以我说我应该亲自动手并开始编码!
我有一个 smiple API 调用,它接收 JSON 数据,然后输出包含所有项目的 ul
列表。我已经为动画集成了 GSAP TweenMax,我想要实现的目标非常简单——我在加载时淡入所有内容,然后 onclick
我想淡出一个元素并将其从 [=26] 中删除=]/数据。
似乎正在发生的事情是该元素正在淡出,正在重新呈现整个 ul
列表并且该元素保留在 DOM 中且不透明度为 0:
var Item = {
list: function() {
return m.request({method: 'GET', url: '/api/items'});
}
}
var dm = {
controller: function(data) {
var items = Item.list();
return {
items: items,
remove: function(item) {
items().data.splice(items().data.indexOf(item), 1);
}
}
},
view: function(ctrl) {
return m('ul', [
ctrl.items().data.map(function(item, id){
return m('li',{
key: id,
config: fadesIn,
onclick: fadeOut(ctrl.remove.bind(this, item))
}, item.title);
})
]);
}
}
var fadesIn = function(element){
var tl = new TimelineMax();
tl.from(element, .5, {opacity: 0});
}
var fadeOut = function(callback) {
return function(e) {
m.redraw.strategy('none');
TweenMax.to(e.target, .5, {opacity: 0, onComplete: function() {
m.startComputation();
callback();
m.endComputation();
}});
}
}
m.mount(document.getElementById('test'), dm);
我很新..昨天才开始阅读。
让动画库与 Mithril 一起工作可能很棘手。当库操纵 DOM 状态时,与 Mithril 状态的同步可能会中断。
幸运的是,情况并非如此:您缺少的是配置函数的 isInitialized
参数,它仅在第一次调用时为 false。对此进行测试使淡入只发生一次:
var fadesIn = function(element, isInit){
if(isInit) return;
var tl = new TimelineMax();
tl.from(element, .5, {opacity: 0});
}
在这个简单的例子中重绘也可以被简化,我做了一个fiddle有一个工作的例子:
http://jsfiddle.net/ciscoheat/dkyc0ryc/
因为没有 DOM 操作,调用 m.redraw
就足以从 DOM 中删除 div,但您使用 [= 可能是正确的13=] 当事情变得更复杂时。我什至会将 m.startComputation
移动到 TweenMax.to
调用上方以使其更加安全,但如果同时发生许多其他事情,则可能会阻止其他重绘。你必须找到一个平衡点。 :)
我认为在任何情况下都不需要调用 m.redraw.strategy
。它主要用于当你不想发生任何事情时(也同步),但是异步动画正在启动,所以它不会有任何效果。
编辑:又发现一个问题,key
不能设置为map函数的索引,那么当一个item被移除时它会改变,搞砸了重绘。我已将 fiddle 更新为使用 item.title
作为键。