Контролируйте и точно измеряйте, как долго изображение отображается

Короткие и простые: поскольку элементы, которые вы ищете, не существуют в документе (пока).


В оставшуюся часть этого ответа я буду использовать getElementById как пример, но то же самое относится к getElementsByTagName , querySelector и любому другому методу DOM, который выбирает элементы.

Возможные причины

Есть две причины, по которым элемент может не существовать:

  1. Элемент с переданным идентификатором действительно не существует в документе. Вы должны дважды проверить, что идентификатор, который вы передаете на getElementById, действительно соответствует идентификатору существующего элемента в (сгенерированном) HTML и что у вас не было с ошибкой идентификатор (идентификаторы чувствительный !). Кстати, в большинстве современных браузеров , которые реализуют методы querySelector() и querySelectorAll(), нотация стиля CSS используется для извлечения элемента его id, например: document.querySelector('#elementID'), в отличие от способа, с помощью которого элемент извлекается его id в [[16]; в первом символе # необходимо, во втором это приведет к тому, что элемент не будет извлечен.
  2. Элемент не существует в данный момент , который вы вызываете getElementById ].

Последний случай довольно распространен. Браузеры анализируют и обрабатывают HTML сверху вниз. Это означает, что любой вызов элемента DOM, который встречается до появления этого элемента DOM в HTML, не будет выполнен.

Рассмотрим следующий пример:



Появляется div после script. В настоящий момент сценарий выполняется, элемент не существует , но и getElementById вернут null.

jQuery

То же самое относится к все селекторы с jQuery. jQuery не найдет элементов, если вы ошибочно написали ваш селектор, или вы пытаетесь выбрать их , прежде чем они на самом деле существуют .

Добавленный поворот - это когда jQuery не найден потому, что вы загрузили скрипт без протокола и запускаетесь из файловой системы:


этот синтаксис используется, чтобы позволить сценарию загружаться через HTTPS на странице с протоколом https: // и для загрузки HTTP-версии на странице с протоколом http: //

У этого есть неудачный побочный эффект попытки и невозможность загрузить file://somecdn.somewhere.com...


Решения

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

Это может быть обеспечено просто добавив ваш JavaScript после к соответствующему элементу DOM

, и в этом случае вы также можете поместить код непосредственно перед тегом закрывающего тела () (все DOM элементы будут доступны в момент выполнения скрипта). [/ g3 6]

Другие решения включают прослушивание событий load [MDN] или DOMContentLoaded [MDN] . В этих случаях не имеет значения, где в документе вы помещаете код JavaScript, вам просто нужно запомнить, чтобы весь обработчик DOM обрабатывался в обработчиках событий.

Пример:

window.onload = function() {
    // process DOM elements here
};

// or

// does not work IE 8 and below
document.addEventListener('DOMContentLoaded', function() {
    // process DOM elements here
});

Более подробную информацию об обработке событий и различиях браузера см. в статьях на странице quirksmode.org .

jQuery

Сначала убедитесь, что jQuery загружен правильно , Используйте инструменты разработчика браузера , чтобы узнать, был ли найден файл jQuery и исправлен ли URL-адрес, если он не был (например, добавьте схему http: или https: в начале, отрегулируйте путь, и т. д.)

Прослушивание событий load / DOMContentLoaded - это именно то, что делает jQuery с .ready() [docs] . Весь ваш код jQuery, который влияет на элемент DOM, должен находиться внутри этого обработчика событий.

На самом деле в учебнике j8uery явно указано:

Как почти все, что мы делаем при использовании jQuery, читает или манипулирует объектной моделью документа (DOM), мы должны убедиться, что мы начинаем добавлять события и т. д., как только DOM готов.

Для этого мы регистрируем готовое событие для документа.

$(document).ready(function() {
   // do stuff when DOM is ready
});
blockquote>

В качестве альтернативы вы также можете использовать сокращенный синтаксис:

$(function() {
    // do stuff when DOM is ready
});

Оба эквивалентны.

26
задан Community 23 May 2017 в 12:06
поделиться

2 ответа

Поскольку я еще не получил больше ответов, но многому научился, редактируя этот вопрос, я публикую свой прогресс в качестве ответа. Как вы увидите, он все еще не оптимален, и я с радостью присужду награду любому, кто его улучшит.

Статистика

New results

  • В самой левой панели вы можете увидеть распределение, которое заставило меня усомниться в оценках времени, которые я получал.
  • Средняя панель показывает, чего я достиг после кэширования селекторов, переупорядочения некоторых вызовов, использования некоторого большего количества цепочек, минимизации перекомпоновок с использованием visibility и абсолютного позиционирования вместо display.
  • Крайняя правая панель показывает, что я получил после использования адаптированной функции Джо Ламберта с использованием requestAnimationFrame. Я сделал это после чтения блога о том, что rAF теперь тоже имеет точность до миллисекунды . Я думал, что это только поможет мне сгладить анимацию, но, очевидно, это также поможет улучшить фактическую длительность отображения .

Результаты

На последней панели среднее значение для времени «отрисовки к краске» составляет ~ 500 мс, среднее значение для разброса времени выполнения в линейном режиме реально (имеет смысл, потому что я использую то же самое временная метка для завершения внутреннего цикла ниже) и коррелирует с синхронизацией «от краски к краске».

В длительности всё ещё есть большая разница, и я бы хотел уменьшить её, но это определённо прогресс. Мне придется протестировать его на некоторых более медленных и некоторых компьютерах с Windows, чтобы увидеть, действительно ли я доволен этим, изначально я надеялся получить все отклонения ниже 10 мс.

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

window.requestTimeout с использованием window.requestAnimationFrame

window.requestTimeout = function(fn, delay) {
    var start = performance.now(),
        handle = new Object();
    function loop(){
        var current = performance.now(),
            delta = current - start;

        delta >= delay ? fn.call() : handle.value = window.requestAnimationFrame(loop);
    };
    handle.value = window.requestAnimationFrame(loop);
    return handle;
};

Редактировать:

Ответ на другой мой вопрос связан с хорошей новой статьей . [одна тысяча сто двадцать-два]

5
ответ дан Community 23 May 2017 в 12:06
поделиться

Вы пытались получить начальные миллисекунды, и после того, как событие было запущено, рассчитать разницу? вместо setTimeout. что-то вроде:

var startDate = new Date();
var startMilliseconds = startDate.getTime();

// when the event is fired :
(...), function() {
    console.log(new Date().getTime() - startMilliseconds);
});

старайтесь по возможности избегать использования jQuery. обычный JS даст вам лучшее время отклика и лучшую общую производительность

4
ответ дан canolucas 23 May 2017 в 12:06
поделиться
Другие вопросы по тегам:

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