动态更改DOM元素,因为它们被滚动到视图中(性能)

时间:2010-01-26 08:55:47

标签: javascript jquery dom

我正在尝试找到一种有效的算法来动态加载一堆<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的元素,这会是一个更好的方法吗?

3 个答案:

答案 0 :(得分:1)

听起来你的应用程序会进行大量的重排和重新绘制,这对于用户体验来说是一个重大的性能损失以及糟糕的HTTP流量。

你有没有想过可能会在同一时间生成相关的CSS时在运行中进行spriting。这样你就可以减少HTTP请求并减少重绘/重排的次数。

答案 1 :(得分:1)

DOM很慢。要获得原始速度,您需要使用innerHTML 为了避免字符串操作,你可以考虑一个JS模板引擎,它们有很多。
我们已经构建了模板引擎PURE,因为它很小而且很快,它可以很好地构建页面手机。

另一种选择可能是考虑上游问题。您确定要为您的用户提供数百/数千个项目的列表吗?

答案 2 :(得分:1)

首先,我建议使用分析器来了解减慢代码速度的原因。有火狐(萤火虫),铬和探险家的个人资料。但我现在可以想到一些问题。

我认为所有LI都是相同UL的子级,因此您可以直接访问它们(firstChild / nextSibling)而无需调用$()。即使有多个UL,直接访问仍然比$()快。

另一个可能的原因是复杂的CSS。我见过一个案例,因为浮动太多并且定位单个访问元素的offsetTop需要半秒钟。这可能会影响.height().position()的速度。

但首先是个人资料!