我正在尝试找到一种有效的算法来动态加载一堆<li>
的背景图像,并且存在一些效率问题。我目前的代码如下:
function elementInView($elem, vps, vpe) {
var elempos = $elem.position();
var pagestart = elempos.top + vps;
var pageend = elempos.top + vps + $elem.height();
var offset = 78 - Math.max(0,vps-pagestart) - Math.max(0,pageend-vpe);
// I want to update all items that are within 200 pixels of
// the current viewport
return (vpe > 0 && offset > -200);
}
$('#container').bind('scroll', function() {
var $container = $(this);
var vps = $container.scrollTop();
var vpe = vps + $container.height();
$('li:not(.bgset)', '#container').each(function() {
var $this = $(this);
if (elementInView($this,vps,vpe)) {
$this.addClass('.bgset');
// Set the background-image (doesn't affect performance noticably.)
}
});
});
在包含约250项的列表中需要200-600毫秒,对于包含~1500项的列表需要约1500毫秒,这使得它几乎无法使用。
任何人都可以看到任何问题,或者这基本上是最好的方法吗?我已尝试获取所有<li>
而不是$('li:not(.bgset)'
,但这根本没有任何影响。
(该列表包含动态生成的背景图像(不会被缓存并且得到很多改变),加载大约1500个它们确实减慢了一切,这就是我尝试这种方法的原因)
编辑:忘了提一下,我想过编写一个自定义的jQuery选择器,它匹配那些为elementInView
返回true的元素,这会是一个更好的方法吗?
答案 0 :(得分:1)
听起来你的应用程序会进行大量的重排和重新绘制,这对于用户体验来说是一个重大的性能损失以及糟糕的HTTP流量。
你有没有想过可能会在同一时间生成相关的CSS时在运行中进行spriting。这样你就可以减少HTTP请求并减少重绘/重排的次数。
答案 1 :(得分:1)
DOM很慢。要获得原始速度,您需要使用innerHTML
为了避免字符串操作,你可以考虑一个JS模板引擎,它们有很多。
我们已经构建了模板引擎PURE,因为它很小而且很快,它可以很好地构建页面手机。
另一种选择可能是考虑上游问题。您确定要为您的用户提供数百/数千个项目的列表吗?
答案 2 :(得分:1)
首先,我建议使用分析器来了解减慢代码速度的原因。有火狐(萤火虫),铬和探险家的个人资料。但我现在可以想到一些问题。
我认为所有LI都是相同UL的子级,因此您可以直接访问它们(firstChild
/ nextSibling
)而无需调用$()
。即使有多个UL,直接访问仍然比$()
快。
另一个可能的原因是复杂的CSS。我见过一个案例,因为浮动太多并且定位单个访问元素的offsetTop
需要半秒钟。这可能会影响.height()
和.position()
的速度。
但首先是个人资料!