我如何处理一个包含数百个HTML项目的列表? (使用Javascript)

我正在创建一个专门用于移动Safari的网页,并且我动态创建了一个列表。 该列表是从我接收信息的文本文件创建的,我将这些信息附加到列表中。 当有大约200个项目时它工作正常,但是当文件非常大时(我尝试了多达4000个项目)页面变得非常慢,滚动和选择这些项目非常困难。 我知道我不应该创建这么多的HTML元素,但我正在寻找一种方法来创建一个较短的列表,并根据您所做的滚动次数来替换列表元素上的信息。 有任何想法吗?


澄清

为了简单起见,我将从一开始就使用专门的JavaScript UI库的可能性。 就个人而言,我不会使用这样的解决方案,因为参与一个库会为您的项目创建额外的约束(可能会膨胀)(除非您正在开发一个严重依赖于客户端UI组件的项目,在这种情况下,您应该选择一个UI库并坚持下去)。

另外,我不会将“滚动”看作解决方案(即创建一个无限的DOM对象列表并简单地滚动浏览它们)。 恕我直言,这不是一个真正的解决问题的方法,它只是一个产生问题的方法。

思考流量

您必须记住,在客户端,JavaScript语言在某种意义上被“附加”到浏览器的文档对象模型中。 您的JavaScript代码实际上“告诉”浏览器以各种方式修改DOM层次结构,然后浏览器符合要求。 这是纯JavaScript代码运行速度加快的主要原因,然后在开始操作DOM对象时速度会大幅下降。

在我看来,遵循的主要规则是通过遵循这个流程尽可能地减少DOM对象操作的数量:

  • 如果可能的话,在服务器端进行:这可以证明是一个非常一致和可靠的解决方案; 如果您的项目允许这样做,那么您应该只在任何一次(例如整个集合中的一个页面)上将合理大小的数据段发送到浏览器,这将使客户端能够快速正确显示和处理该数据和响应的方式。

  • 如果您必须在客户端执行此操作,请尽可能避免触摸DOM:这很重要; 如果您在JS脚本中接收到4000个对象,请将它们保存在内存中,不要急于将所有这些元素转换为DOM对象; 这是一个死刑。

  • 仅在最后可能的时刻操作DOM并触及最少量的对象:因为修改DOM需要付出很多努力(与其他内存操作相比)。 这里存在的另一个危险是内存泄漏(浏览器并不完美),因为在创建和丢弃许多DOM对象时,某些被丢弃的对象可能仍然在内存中生存,从而产生内存泄漏(最终可能导致浏览器甚至系统)。

  • 解决方案

    这些是桌上的方法:

  • 服务器端分页 :或许这是显而易见的,但人们试图忽略这个选项的次数太多了,我认为这是错误的。 同样,如果你的项目允许这样做,这样的解决方案很难让你失败:它可以非常一致和可靠(这就是它的典型原因)。

  • 客户端分页 :显然,您可以将整个数据发送到浏览器,在JS中处理它,然后立即以合理大小的块显示它,从不超过一定数量的生成的DOM对象。 这似乎比解决方案1更具吸引力和更简单,但要注意,如果您的数据是双向的(即意味着必须返回服务器的用户的干预和反馈)并且重要(例如更重要的是仅需要统计/报告数据要显示),你应该避免这个选项。

    原因是,即使JavaScript的速度和效率足以在内存中处理这些数据,它也不是那么安全; 你永远不知道客户端会发生什么:内存可能会损坏,浏览器可能崩溃等等。 基本上你对你的数据没有合理的保证。 服务器准备好处理重要数据。 更重要的是,在页面和URL地址之间进行历史浏览将非常困难,而这些地址会转到数据集中的特定页面(无论如何,这两个页面都是可能的,但并非没有头痛)。

  • 客户端动态滚动 :不是将JS内存中的对象显示为完整页面,而是简单地显示一个合理的子集,比方说100个项目,然后通过从顶部取一个对象(或更多)并将其移动到列表的底部,相应地改变它的内容。 显然这个选项和解决方案2有相同的危险,但它仍然是一个非常好的解决方案。

  • 考虑到你的项目适用于移动设备,我认为最后一种方法对你来说可能更加可行,所以这里是一个非常简单的例子,说明如何使用MooTools来完成它(显然这个原则可以用任何框架来实现):

    <html>
    
    <head>
    
        <title>Endless scrolling example.</title>
    
        <!-- Include the MooTools framework. -->
        <script type="text/javascript" src="mootools-1.2.4-core-yc.js"></script>
    
        <!-- Note: we'll use id's to select objects since it's faster. -->
    
    </head>
    
    <body>
    
        <!-- Scroll up. -->
        <a href="javascript:void(0);" id="list_up_button">Up!</a>
    
        <!-- The list (i.e. container). -->
        <ul id="list_container">
        </ul>
    
        <!-- Scroll down. -->
        <a href="javascript:void(0);" id="list_down_button">Down!</a>
    
    </body>
    
    <!-- Our script. -->
    <script type="text/javascript">
    
        window.addEvent('domready', function() {
    
            // database
            var list = {};
    
            // options
            var list_size = 5000;   // total list size
            var list_offset = 0;    // initial list position
            var list_subset = 40;   // the smount of displayed items
            var scroll_step = 10;    // items to scroll in one step
            var time_delay = 50;    // time delay between scroll steps
    
            // make dummy items
            for (var i = 0; i < list_size; i++) {
                var red = Math.floor(i * 2) % 256;
                var green = Math.floor(i * 3) % 256;
                var blue = Math.floor(i * 4) % 256;
    
                list[i] = "<span style="color:rgb(" + red + ", " + green + ", " + blue + ");">" +
                          "My name is 'Object no." + (i + 1) + "'." +
                          "</span>";
            }
    
            // get container
            var list_container = $('list_container')
    
            // generate DOM objects
            for (var i = 0; i < list_subset; i++) {
                list_container.grab(new Element('li', { html: list[i] }));
            }
    
            // Up scroller.
            function up() {
    
                // check end
                if (list_offset <= 0) {
                    return false;
                }
    
                // get element
                var element = list_container.getLast();
    
                // devance offset
                list_offset--;
    
                // re-write element
                element.set('html', list[list_offset]);
    
                // move top element to top
                list_container.grab(element, 'top');
    
                // success
                return true;
            }
    
            // Down scroller.
            function down() {
    
                // check end
                if (list_offset >= list_size - list_subset) {
                    return false;
                }
    
                // get element
                var element = list_container.getFirst();
    
                // advance offset
                list_offset++;
    
                // re-write element
                element.set('html', list[list_offset + list_subset - 1]);
    
                // move top element to bottom
                list_container.grab(element, 'bottom');
    
                // success
                return true;
            }
    
            // Repeater function.
            function repeater(direction) {
    
                for (var i = 0; i < scroll_step; i++) {
    
                    // scroll
                    if (direction() == false) {
    
                        // deactivate repeater
                        $clear(list.scroll_period);
                    }
                }
    
            }
    
            // configure up scroll
            $('list_up_button').addEvents({
    
                // activate scroll
                'mouseenter': function() {
                    list.scroll_period = repeater.periodical(time_delay, null, up);
                },
    
                // deactivate scroll
                'mouseleave': function() {
                    $clear(list.scroll_period);
                }
            });
    
            // configure up scroll
            $('list_down_button').addEvents({
    
                // activate scroll
                'mouseenter': function() {
                    list.scroll_period = repeater.periodical(time_delay, null, down);
                },
    
                // deactivate scroll
                'mouseleave': function() {
                    $clear(list.scroll_period);
                }
            });
    
        });
    
    </script>
    

    对不起,相当长的代码...希望它有帮助。


    不要将这些项目追加到列表中,如何一次显示多达200个,然后在向前滚动中替换当前项目 - 向后滚动运动? 您可以使用innerHTML或创建元素的DOM方法。


    你可以创建类似“虚拟滚动”的东西 - 只显示几个项目(可以在屏幕上查看),并通过补偿边距使滚动条出现。 这样,你会让用户认为他在屏幕上有4000个项目,并且只有20个项目在内存中。

    链接地址: http://www.djcxy.com/p/2435.html

    上一篇: How can I handle a list with several hundred items in HTML? (Using Javascript)

    下一篇: dynamically adding a view to activity layout