Манипулирование innerHTML в JavaScript
-
09-06-2019 - |
Вопрос
Я разрабатываю код веб-страницы, который динамически извлекает содержимое с сервера, а затем помещает это содержимое в узлы контейнера, используя что-то вроде
container.innerHTML = content;
Иногда мне приходится перезаписывать некоторое предыдущее содержимое в этом узле.Это работает нормально, пока не случится так, что предыдущий контент занимал больше места по вертикали, чем занимал бы новый, И пользователь прокрутил страницу вниз - прокрутил больше, чем позволил бы новый контент, при условии его высоты.
В этом случае страница перерисовывается неправильно - сохраняются некоторые артефакты старого содержимого.Это работает нормально, и даже можно избавиться от артефактов, свернув и восстановив браузер (или принудительно перерисовать окно другим способом), однако это кажется не очень удобным.
Я тестирую это только в Safari (это веб-сайт, оптимизированный для iPhone).
У кого-нибудь есть идея, как с этим справиться?
Решение
Самым простым решением, которое я нашел, было бы разместить тег привязки <a>
в верхней части div
вы редактируете:
<a name="ajax-div"></a>
Затем, когда вы измените содержимое div
, вы можете сделать это , чтобы браузер перешел к вашему тегу привязки.:
location.hash = 'ajax-div';
Используйте это, чтобы убедиться, что пользователь не прокручивается слишком далеко вниз при обновлении содержимого, и вы не должны столкнуться с проблемой в первую очередь.
(протестировано в последней бета-версии FF и последней версии safari)
Другие советы
Похоже, что механизм рендеринга webkit в Safari сначала не распознает изменение содержимого, по крайней мере, недостаточно полно, чтобы удалить предыдущее содержимое html.Сворачивание, а затем восстановление Windows инициирует событие перерисовки в механизме рендеринга браузера.
Я думаю, что я бы исследовал 2 пути:во-первых, могу ли я использовать iframe вместо текущего узла "content"?Браузеры ожидают, что IFrames изменятся, однако, как вы видите, они не всегда так хороши в изменении содержимого DIV или других элементов.
Во-вторых, возможно, изменив положение прокрутки, как было предложено ранее.Вы могли бы просто переместить прокрутку обратно в 0, как предложено, или, если это слишком навязчиво, вы могли бы попытаться восстановить прокрутку после изменения содержимого.Вычтите высоту старого узла содержимого из текущей позиции прокрутки (сбросив значение прокрутки браузера до 0 для узла содержимого), измените содержимое узла, затем добавьте высоту нового узла к позиции прокрутки.
Хотя Пейлхорс прав (на данный момент я не могу проголосовать за его ответ - нет баллов), библиотека абстракций, такая как jQuery, Dojo или даже Prototype, часто может помочь в этих вопросах.Особенно, если вы видите, что ваша страница / сайт выходит за рамки простых манипуляций с DOM, вы обнаружите, что инструменты и усовершенствования, предоставляемые библиотеками, окажут вам огромную помощь.
Похоже, у вас возникла проблема с самим браузером.Возникает ли эта проблема только в одном браузере?
Одна вещь, которую вы могли бы попробовать, - это использовать облегченную библиотеку, такую как jQuery.Он довольно хорошо справляется с различиями в браузерах.Чтобы установить внутренний HTML-код для div с идентификатором контейнер вы бы просто написали это:
$('#container').html( content );
Это будет работать в большинстве браузеров.Я не знаю, решит ли это конкретно вашу проблему или нет, но, возможно, стоит попробовать.
Сработает ли установка положения прокрутки обратно в верхнее положение (element.scrollTop = 0;элемент.scrollLeft = 0;наизусть) перед заменой содержимого?
Устанавливайте высоту CSS элемента в значение "auto" каждый раз, когда вы обновляете innerHTML.
Я бы попробовал сделать container.innerHTML = ";container.innerHTML = содержимое;