сжать HTML-помощь

У меня есть массив из 2000 элементов, которые мне нужно отобразить в html - каждый из элементов помещается в div. Теперь каждый из элементов может иметь 6 ссылок, по которым можно перейти для дальнейших действий. Вот как в настоящее время выглядит один элемент:

<div class='b'>
  <div class='r'>
    <span id='l1' onclick='doSomething(itemId, linkId);'>1</span>
    <span id='l2' onclick='doSomething(itemId, linkId);'>2</span>
    <span id='l3' onclick='doSomething(itemId, linkId);'>3</span>
    <span id='l4' onclick='doSomething(itemId, linkId);'>4</span>
    <span id='l5' onclick='doSomething(itemId, linkId);'>5</span>
    <span id='l6' onclick='doSomething(itemId, linkId);'>6</span>
  </div>
  <div class='c'>
  some item text
  </div>
</div>

Теперь проблема с производительностью. Я использую innerHTML для установки элементов в главный div на странице. Чем больше html содержит мой «отдельный элемент», тем больше времени требуется DOM для его добавления. Сейчас я пытаюсь уменьшить HTML, чтобы сделать его как можно меньше. Есть ли способ отображать диапазоны по-разному, чтобы мне не приходилось использовать один диапазон для каждого из них? Может быть, с помощью jQuery?


person vikasde    schedule 17.11.2009    source источник
comment
это нужно делать в браузере? Вы не можете организовать веб-сервер для доставки контента, как вы этого хотите?   -  person Scott Evernden    schedule 17.11.2009
comment
Но мне все равно пришлось бы отображать контент с помощью innerHTML или append. Все равно будет медленно.   -  person vikasde    schedule 17.11.2009
comment
Можете ли вы дать нам краткий пример массива, чтобы мы могли написать для вас ответ бога?   -  person Matt Smith    schedule 17.11.2009
comment
obj[0] = {Элемент: 2001, Описание: некоторое описание, InZones: 1,2,3}; InZones используется для создания пролетов. Всего их всегда 6. Если в InZones есть что-то, то класс соответствующего спана нужно изменить на sel. Надеюсь, это имеет смысл.   -  person vikasde    schedule 17.11.2009
comment
Вы добавляете innerHTML в цикл для каждого из диапазонов или для всех диапазонов вместе только один раз?   -  person gpilotino    schedule 17.11.2009
comment
Если всегда есть 6 интервалов, я предполагаю, что они находятся в элементе контейнера. Просто клонируйте фрагмент HTML и обновите уже клонированный HTML, добавив в него отличия. Это может быть быстрее, чем создание одного большого обновления innerHTML. Просто мысли вслух, пока я заканчиваю свой обед ;)   -  person nickytonline    schedule 17.11.2009
comment
@gpilotino: я перебираю все промежутки и добавляю их в строку, которую затем использую для html.   -  person vikasde    schedule 17.11.2009
comment
@nickyt: Могу ли я сначала создать шаблон SPAN и добавить его в скрытый DOM, прежде чем клонировать его? Сейчас я перебираю все элементы размером 2 КБ и для каждого элемента создаю промежутки.   -  person vikasde    schedule 17.11.2009
comment
@vikasde - Да, шаблон SPAN подходит для того, что вам нужно. Вы можете сделать это самостоятельно или, возможно, посмотреть, что Мэтт Смит упоминает в своем ответе о фрагментах документов г-на Рейзига.   -  person nickytonline    schedule 17.11.2009


Ответы (5)


Первое, что вы должны сделать, это прикрепить событие onclick к DIV через jQuery или какую-либо другую структуру и позволить ему всплывать, чтобы вы могли использовать doSomething для охвата всех случаев, и в зависимости от того, на какой элемент вы нажали, вы можете извлечь идентификатор элемента и идентификатор ссылки. Также действительно ли промежуткам нужны идентификаторы? Я не знаю, основываясь на вашем примере кода. Кроме того, возможно, вместо того, чтобы загружать ссылку и идентификаторы элементов при загрузке страницы, получайте их через AJAX по мере необходимости.

Мои пять копеек, когда я ем салат на обед, Никит.

Свежее обновление для vikasde. Синтаксис этого может быть не совсем правильным. Я на обеденном перерыве.

$(".b").bind( // the class of your div, use an ID , e.g. #someID if you have more than one element with class b
    "click",
    function(e) { // e is the event object
        // do something with $(e.target), like check if it's one of your links and then do something with it.
    }
);
person nickytonline    schedule 17.11.2009
comment
Пробовал использовать загрузку onDemand через ajax, но менеджеры решили, что нужно все сразу на странице. Как я могу использовать jQuery для всплытия события клика? - person vikasde; 17.11.2009

Если вы установите свойство InnerHtml узла, DOM должен будет интерпретировать ваш HTML-текст и преобразовать его в узлы. По сути, здесь вы используете интерпретатор языка. Больше текста, больше времени на обработку. Я подозреваю (но не уверен), что было бы быстрее создать фактические узлы элементов DOM со всей необходимой вложенностью содержимого и подключить их к содержащему узлу. Ваше решение «InnerHTML» делает то же самое под прикрытием, но также выполняет дополнительную работу по осмыслению вашего текста.

Я также поддерживаю предложение кого-то другого, который сказал, что может быть более экономичным создавать весь этот контент на сервере, а не в клиенте через JS.

Наконец, я думаю, вы можете удалить большую часть содержимого ваших span. Вам не нужен идентификатор, вам не нужны аргументы в вашем onclick(). Вызовите функцию JS, которая определит, из какого узла она вызывается, поднимитесь на один узел вверх, чтобы найти содержащий div, и, возможно, прокрутите содержащиеся узлы и/или просмотрите текст, чтобы выяснить, на какой элемент в div он должен реагировать. . Вы можете заставить обработчик onclick выполнять много работы - эта работа выполняется только один раз, во время щелчка мыши, и не будет умножаться на 2000x. Это не займет ощутимого количества времени пользователя.

person Carl Smotricz    schedule 17.11.2009
comment
Разве innerHTML не считается быстрее, чем добавление? - person vikasde; 17.11.2009
comment
Что ж, я могу себе представить, что происходит, так это то, что vikasde постоянно делает что-то ужасное вроде innerHtml = innerHtml + anotherSpan. Таким образом, чтобы получить 6 пролетов, он фактически строит 21, 15 из них для битового ковша. Это должно быть ужасно с точки зрения производительности. В приличной реализации браузера добавление узлов, если все сделано правильно, должно быть быстрее. Хитрость заключается в том, чтобы собрать новый материал незаметно, чтобы он не запускал обновления браузера, пока не будет выполнено. - person Carl Smotricz; 17.11.2009
comment
@Carl: я создаю строку в js, и когда я закончу всю строку, я использую innerHTML - я использую это только один раз. - person vikasde; 17.11.2009
comment
Жаль, это было бы легкой целью оптимизации! Я стою исправленным и с яичным лицом из-за негативного предположения. - person Carl Smotricz; 17.11.2009
comment
Следующим моим предложением было бы создать весь этот контент с классом display: none и переключить класс на видимый, как только вы закончите со всем зданием. Если ваш браузер обновляется после каждой вставки, отсюда и ваша задержка. Это также объясняет, почему (если) он становится медленнее, чем больше строк у вас есть. - person Carl Smotricz; 17.11.2009
comment
Я не думал об этом на самом деле. Позвольте мне попробовать это и посмотреть, как это идет. - person vikasde; 17.11.2009
comment
Кажется, это работает. Спасибо. Однако теперь я замечаю, что мой браузер реагирует немного медленнее. Например, когда я навожу мышь на ссылку, то я не вижу сразу стандартный курсор ссылки - проходит около 2-3 секунд, прежде чем я его вижу, а когда я вывожу мышь из ссылки, то он снова занимает 2-3 секунды, прежде чем я вижу стандартный курсор мыши. Задержка точно есть. Есть ли способ исправить это? - person vikasde; 17.11.2009
comment
С таким количеством информации в буфере вашему браузеру нужна кислородная палатка и кардиостимулятор (это мое предположение). Вы можете проверить использование памяти извне и убедиться, что ваш javascript не пропускает память (т.е. создает объекты и держится за них дольше, чем необходимо). Вы можете попробовать эту страницу в разных браузерах? - person Carl Smotricz; 18.11.2009
comment
Для нас он должен работать в IE, так как наша компания стандартизирована для него. Я протестировал его в Firefox, и он работает очень гладко, без каких-либо задержек. - person vikasde; 18.11.2009
comment
Да, я думал, ты это скажешь. Я думаю, это означает, что решение неплохое, а с остаточными проблемами трудно бороться, потому что они связаны с браузером. Если вы видите еще один шанс сократить сложность страницы, сделайте это! Кроме того, появляется еще одно возможное решение. - person Carl Smotricz; 18.11.2009
comment
Я думаю, что лучше всего было бы добавить элементы в DOM только для видимой области и удалить все остальные, а при прокрутке добавить новые видимые элементы обратно в DOM. - person vikasde; 18.11.2009
comment
Очень круто! Очень впечатляюще. Вы можете быть на что-то здесь. Но, конечно, мое последнее предложение намного лучше;) См. Еще одно решение. - person Carl Smotricz; 18.11.2009

Джон Резиг написал блог на documentDragments http://ejohn.org/blog/dom-documentfragments/

Мое предложение состоит в том, чтобы создать documentDragment для каждой строки и добавить ее в DOM по мере ее создания. timeout обертывание каждого appendChild может помочь, если есть какие-либо зависания в браузере

function addRow(row) {
    var fragment = document.createDocumentFragment();

    var div = document.createElement('div');
    div.addAttribute('class', 'b');

    fragment.appendChild(div);
    div.innerHtml = "<div>what ever you want in each row</div>";

    // setting a timeout of zero will allow the browser to intersperse the action of attaching to the dom with other things so that the delay isn't so noticable
    window.setTimeout(function() { 
        document.body.appendChild(div);
    }, 0);
};

надеюсь, это поможет

person Matt Smith    schedule 17.11.2009
comment
Вы правы, я протестировал несколько таких методов, но самое главное в этом скрипте — это setTimeout. Если вы добавляете каждую строку по одной, страница остается интерактивной, пока добавляются другие строки. Другой способ сделать это - если бы вы могли - добавить каждую строку без 6 маркеров зон, а затем снова перебрать их, как только они будут добавлены в DOM, и добавить соответствующие маркеры зон - в основном визуально создавая страницу в битах. - person Matt Smith; 18.11.2009

Еще одна проблема заключается в том, что на странице слишком много всего, что ваш браузер не может корректно обработать. Я не уверен, позволяет ли это дизайн страницы, но как насчет того, чтобы поместить эти 2000 строк в DIV с фиксированным размером и overflow: auto, чтобы пользователь получил прокручиваемое окно на странице?

Это не то, что я бы предпочел как пользователь, но если это исправит странность курсора, это может быть приемлемым обходным путем.

person Carl Smotricz    schedule 18.11.2009

Еще одно решение

... к проблеме "слишком много материала на странице":

(пожалуйста, дайте мне знать, когда вам надоест эти предложения!)

Если у вас есть возможность использовать встроенный объект, скажем, Java-апплет (мое личное предпочтение, но большинство людей его не трогает), JavaFX, Flash, Silverlight или...

тогда вы могли бы отображать все эти странные данные в этой технологии, встроенные в страницу вашего браузера. Содержимое страницы не должно касаться браузера, и, следовательно, он не задохнется от вас.

Помимо времени загрузки для Java или чего-то еще, это может быть прозрачным и невидимым для пользователя, то есть (почти) возможно сделать так, чтобы текст отображался на странице так же, как если бы он был непосредственно в HTML.

person Carl Smotricz    schedule 18.11.2009
comment
Я учту и это. Я пытаюсь использовать свой нынешний подход к работе. - person vikasde; 18.11.2009
comment
Может быть, вы поможете и мне с этим? stackoverflow .com/questions/1757106/ - person vikasde; 18.11.2009