Разъяснение
Для простоты я с самого начала буду использовать возможность использования специализированной библиотеки JavaScript UI. Лично я бы не использовал такое решение, так как участие в библиотеке создает дополнительные ограничения (и, возможно, раздувание) для вашего проекта (если вы не работаете над проектом, который в значительной степени опирается на компоненты пользовательского интерфейса на стороне клиента, и в этом случае вы должны выбрать один). Библиотека пользовательского интерфейса и придерживаться ее).
Кроме того, я не буду рассматривать «прокрутку» как решение (то есть создание бесконечного списка объектов DOM и простую прокрутку по ним). ИМХО, на самом деле это не «решение» проблемы, это просто метод генерации проблемы, которая привела вас сюда.
Думай поток
Вы должны иметь в виду, что на стороне клиента язык JavaScript в некотором смысле «привязан» к объектной модели документа в браузере. Ваш код JavaScript практически «говорит» браузеру, что нужно изменить иерархию DOM множеством способов, и тогда браузер согласится. Это основная причина, по которой чистый JavaScript-код имеет тенденцию работать быстро, а затем резко замедляется, когда начинаешь манипулировать объектами DOM.
Основное правило, которому нужно следовать, на мой взгляд, состоит в том, чтобы максимально минимизировать количество манипуляций с объектами DOM, следуя этому потоку:
Если возможно, сделайте это на стороне сервера : это может оказаться очень последовательным и надежным решением; если ваш проект допускает это, вы должны отправлять в браузер только сегменты данных разумного размера (например, одну страницу из всего набора), это позволит клиенту правильно отображать и обрабатывать эти данные в кратчайшие сроки. и отзывчивый способ.
Если вы должны сделать это на стороне клиента, старайтесь не трогать как можно больше DOM : это важно; если вы получаете 4000 объектов в JS-скрипте, храните их в памяти , не спешите переводить все эти элементы в объекты DOM; это смертный приговор.
Манипулировать DOM только в последний возможный момент и касаться наименьшего количества объектов : поскольку для модификации DOM требуется много усилий (по сравнению с другими Операции с памятью). Другая опасность здесь - утечка памяти (браузеры не идеальны), так как при создании и отбрасывании многих объектов DOM некоторые из этих отброшенных объектов могут все еще сохраняться в памяти, что приводит к утечке памяти (которая может в конечном итоге привести к зависанию браузера или даже системы). ).
Решения
Вот подходы на столе:
Разбивка на стороне сервера : возможно, это очевидно, но слишком часто люди пытаются пропустить этот вариант, и я думаю, что это неправильно. Опять же, если ваши проекты позволяют это, очень трудно для такого решения подвести вас: оно может быть очень последовательным и надежным (вот почему это classic ).
Разбиение на стороне клиента : Очевидно, что вы можете отправить все данные в браузер, обработать их в JS, а затем сразу отобразить в виде кусков разумного размера, не превышая определенного количества сгенерированные объекты DOM. Это может показаться привлекательным и более простым, чем Решение 1, однако, имейте в виду, что если ваши данные являются двунаправленными (то есть подразумевают вмешательство и обратную связь от пользователя, которые должны вернуться на сервер) и важными (например, более важными, чем статистические данные / данные отчетности, которые нужны только ), вам, вероятно, следует избегать этой опции.
Причина в том, что даже если JavaScript достаточно быстрый и эффективный для манипулирования этими данными в памяти, он не настолько безопасен ;Вы никогда не знаете, что может произойти на стороне клиента: память может быть повреждена, может произойти сбой браузера и т. д. ;в основном у вас нет разумной гарантии для ваших данных.Сервер лучше подготовлен для обработки важных данных.Более того, будет очень трудно иметь историю навигации между страницами и URL-адресами, которые переходят на конкретные страницы в наборе данных (оба возможны, но в любом случае не без головной боли).
Клиентская динамическая прокрутка : вместо отображения объектов из памяти JS в виде полных страниц, вы просто показываете разумное подмножество, скажем, 100 элементов, а затем прокручиваете вниз, беря один объект (или больше)сверху вниз и перемещая его в конец списка, соответственно изменяя его содержимое.Очевидно, что этот вариант представляет те же опасности, что и решение 2, но все же это очень хорошее решение.
Пример
Учитывая, что ваши проекты работают на мобильных устройствах, я считаю, чтоПоследний подход, вероятно, более выполним для вас, поэтому вот (очень) упрощенный пример того, как это можно сделать с помощью MooTools (очевидно, этот принцип может быть применен с использованием any framework):
<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>
Извините за довольно длинный код ... надеюсь, это поможет.