Как мне обработать список из нескольких сотен элементов в HTML? (Используя Javascript)

Я создаю веб-страницу, которая предназначена для мобильного сафари, и я создаю список динамически. Список создается из текстового файла, в котором я получаю информацию и добавляю эту информацию в список. Он прекрасно работает, когда имеется около 200 элементов, но когда файл очень большой (я пробовал до 4000 элементов), страница становится очень медленной, прокрутка и выбор этих элементов очень сложны. Я знаю, что не должен создавать столько HTML-элементов, но я ищу способ создать более короткий список и заменить информацию об элементах списка в зависимости от того, сколько прокрутки вы сделали. Любые идеи?

7
задан Fernando Casares 18 August 2010 в 18:43
поделиться

5 ответов

Вместо того, чтобы добавлять элементы в список, как насчет одновременного отображения до 200 элементов с последующей заменой текущих элементов при прокрутке вперед-назад? Вы можете использовать для этого innerHTML или методы DOM, которые создают элементы.

0
ответ дан 7 December 2019 в 16:37
поделиться

Уточнение

Чтобы не усложнять ситуацию, я с самого начала опущу возможность использования специализированной библиотеки JavaScript UI. Лично я не стал бы использовать такое решение, поскольку работа с библиотекой создает дополнительные ограничения (и, возможно, раздувает ваш проект) (если только вы не работаете над проектом, который сильно зависит от компонентов пользовательского интерфейса на стороне клиента, в этом случае вам следует выбрать одну библиотеку пользовательского интерфейса и придерживаться ее).

Также я не буду рассматривать "прокрутку" в качестве решения (т.е. создание бесконечного списка объектов DOM и простое прокручивание их). IMHO это не совсем "решение" проблемы, это просто метод создания проблемы, который привел вас сюда.

Поток мышления

Вы должны помнить, что на стороне клиента язык JavaScript в некотором смысле "привязан" к объектной модели документа браузера. Ваш код JavaScript практически "говорит" браузеру изменить иерархию DOM огромным количеством способов, а браузер подчиняется. Это основная причина, по которой чистый код JavaScript имеет тенденцию работать быстро, а затем все резко замедляется, когда начинаются манипуляции с объектами DOM.

Главное правило, которому нужно следовать, на мой взгляд, заключается в том, чтобы минимизировать, насколько это возможно для человека, количество манипуляций с объектами DOM, следуя следующей схеме:

  1. Если возможно, делайте это на стороне сервера: это может оказаться очень последовательным и надежным решением; если ваш проект позволяет это, вы должны посылать браузеру только разумно большие сегменты данных в любой момент времени (например. например, одну страницу из всего набора), это позволит клиенту правильно отображать и манипулировать этими данными в быстром и отзывчивом режиме.

  2. Если вы должны делать это на стороне клиента, избегайте касаться DOM как можно больше: это очень важно; если вы получаете 4000 объектов в JS-скрипте, держите их в памяти, не спешите переводить все эти элементы в объекты DOM; это смертный приговор.

  3. манипулируйте DOM только в последний возможный момент и затрагивая наименьшее количество объектов: поскольку модификация DOM требует много усилий (по сравнению с другими операциями в памяти). Другой опасностью здесь является утечка памяти (браузеры не совершенны), так как при создании и удалении большого количества объектов DOM, некоторые из этих удаленных объектов могут все еще оставаться в памяти, создавая утечку памяти (которая в конечном итоге может засорить браузер или даже систему).

Решения

Вот подходы, представленные на столе:

  1. Server-side pagination: возможно, это очевидно, но слишком часто люди пытаются упустить этот вариант, и я считаю это неправильным. Опять же, если ваши проекты это позволяют, то очень сложно, чтобы такое решение вас подвело: оно может быть очень последовательным и надежным (именно поэтому оно является классикой).

  2. Client-side pagination: Очевидно, что вы можете отправить все данные в браузер, обработать их в JS, а затем отобразить их в разумных размерах сразу, никогда не превышая определенного количества сгенерированных DOM-объектов. Это может показаться привлекательным и более простым, чем решение 1, однако следует помнить, что если ваши данные двунаправленные (т.е. предполагают вмешательство и обратную связь с пользователем, которые должны возвращаться на сервер) и важные (например, более важные, чем статистические/отчетные данные, которые нужно только отображать), то вам, вероятно, следует избегать этого варианта.

    Причина в том, что даже если JavaScript достаточно быстр и эффективен, чтобы жонглировать этими данными в памяти, это не так безопасно; вы никогда не знаете, что может произойти на стороне клиента: память может быть повреждена, браузер может упасть и т.д. ; в принципе, у вас нет разумной гарантии сохранности ваших данных. Сервер лучше подготовлен для работы с важными данными. Более того, будет очень трудно обеспечить навигацию по истории между страницами и URL-адреса, ведущие на определенные страницы в наборе данных (и то, и другое возможно, но в любом случае не без головной боли).

  3. Динамическая прокрутка на стороне клиента: вместо того, чтобы отображать объекты из памяти 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>

Извините за довольно длинный код... надеюсь, это поможет.

3
ответ дан 7 December 2019 в 16:37
поделиться

Вы можете создать что-то вроде "виртуальной прокрутки" - показать только несколько элементов (которые можно просмотреть на экране) и заставить появляться полосу прокрутки, смещая их с помощью полей. Таким образом, вы заставите пользователя думать, что у него 4000 элементов на экране, а в памяти у него только 20 элементов.

0
ответ дан 7 December 2019 в 16:37
поделиться

Использовать таблицу данных. Два, о которых я знаю, - это YUI2 dataTable и www.dataTables.net. Я использую www.dataTables.net, потому что он действительно хорош, и я до сих пор к нему довольно привык (хотя и не эксперт). Вы можете использовать обработку на стороне сервера, которую вы можете использовать для вызова php-файла или метода или другого javascript, но он захватит для вас x записей и знает, с чего начать, когда вы просматриваете страницы (разбиение на страницы уже предоставляется с dataTable.

Вы бы создали экземпляр таблицы следующим образом:

<script type="text/javascript" char="utf-8>
  $(document).ready(function() {
    $('#tableName').dataTable({
      "bProcessing": true,
      "bServerSide": true,
      "sAjaxSource": "php_filename.php",
      "sPaginationType": "full_numbers"
    });
  });
</script>

from dataTables.net

Это пример изображения того, как она будет выглядеть. Единственная проблема с обработкой на стороне сервера заключается в том, что вам придется передавать информацию в формате JSON.

 "aaData": [
  "info1",
  "info2",
  etc...
]

Элементы управления также могут быть добавлены в записи aaData. Хороший пример - . Надеюсь, это поможет.

Обновление 2: Вам нужно будет загрузить файл jQuery (я использовал 1.4.1) и сослаться на файл jQuery , файл dataTable.js и css. Имя класса таблицы должно быть "display". Имя css - demo_table.css.

<script type="text/javascript" language="javascript" src="../Scripts/jquery-1.4.1.js"></script>
<script type="text/javascript" language="javascript" src="../Scripts/jquery.dataTables.js"></script>

<style type="text/css" title="currentStyle">
  @import "../../Content/stylesheets/demo_table.css"
</style>
0
ответ дан 7 December 2019 в 16:37
поделиться

Даже если вы хотите отобразить весь большой список за один раз, используйте фрагмент документа

0
ответ дан 7 December 2019 в 16:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: