Статьи

Почему изменение события прокрутки в iOS 8 — большое дело

Автор  TJ VanToll 

Если вы прочитали «Что нового в руководствах по iOS 8», вы, возможно, заметили изменение в том, как работают события прокрутки. Хотя многие могут считать это незначительным изменением, любой разработчик, который пытался внедрить логику прокрутки в мобильном Интернете, знает, что это на самом деле довольно важно. В этой статье я объясню, что изменилось, что это значит, и расскажу одно важное предостережение для разработчиков Cordova.

Краткий урок истории

Когда iOS Safari разрабатывался впервые, инженеры Apple столкнулись с некоторыми сложностями при отображении существующей сети на маленьком экране. Что бы там ни было, многие из их внутренних технических решений стали воплощаться в качестве «функций» сети — таких как сенсорные события, мета-теги области просмотра и так далее. Одним из таких решений было приостановить все выполнение JavaScript всякий раз, когда пользователь прокручивал. Чтобы показать это в действии, рассмотрите следующий код, который считает  scroll события:

var count = 0;
window.addEventListener( "scroll", function( event ) {
    count++;
});

В двух рисунках ниже я отображаю количество событий в фиксированном заголовке и прокручиваю несколько раз. Обратите внимание, что в iOS 7 (слева) счетчик не увеличивается до тех пор, пока прокрутка полностью не прекратится, тогда как в iOS 8 (справа) счетчик постоянно увеличивается.

Пример поведения события прокрутки в iOS 7
Пример поведения события прокрутки в iOS 8

Почему именно Apple приостанавливает выполнение JavaScript во время прокрутки, неясно, но это, скорее всего, связано с производительностью, поскольку веб-разработчики часто злоупотребляют событием прокрутки. В 2011 году, после того, как обработчик события прокрутки сделал Twitter нестабильным для многих пользователей, Джон Резиг  написал статью о проблеме события прокрутки , в которую он включил следующие рекомендации:


Это очень, очень плохая идея — прикреплять обработчики к событию прокрутки окна. В зависимости от браузера событие прокрутки может срабатывать очень часто, и помещение кода в обратный вызов прокрутки замедлит любые попытки прокрутки страницы (не очень хорошая идея). Любое снижение производительности в обработчике прокрутки в результате только ухудшит производительность прокрутки в целом. Вместо этого гораздо лучше использовать некоторую форму таймера, чтобы проверять каждые X миллисекунд ИЛИ прикреплять событие прокрутки и запускать ваш код только после задержки (или даже после заданного количества выполнений — и затем задержки).

Так что поставьте себя на место инженера Apple, работающего над оригинальным iPhone. На многих сайтах выполняется код с высокой производительностью в событиях прокрутки, и это делает ваш браузер нестабильным и медленным. (И помните, мы говорим о работе на оригинальном iPhone, а не на аппаратном обеспечении сегодняшнего дня.) Что вы делаете? По-видимому, вы полностью приостанавливаете выполнение JavaScript во время прокрутки, что является нормальным решением для данной среды.

Последующие мобильные браузеры, в частности IE Mobile и Android-браузер, последовали примеру Apple, возможно, по тем же причинам или, возможно, из-за совместимости. Несмотря на это, отсутствие полезных событий прокрутки стало ограничением всей мобильной сети в течение некоторого времени.

Почему это важно?

Как выясняется, существует много вполне веских причин, по которым вы можете захотеть выполнять действия во время прокрутки, например, эффекты параллакса или бесконечные списки прокрутки, удобные для исполнения. И из-за решения Apple приостановить JavaScript во время прокрутки эти эффекты стали невозможны в мобильном Интернете, по крайней мере, без реализации прокрутки с помощью JavaScript, что на самом деле делают многие библиотеки.

Например, популярная  библиотека iScroll  переопределяет прокрутку с использованием переводов CSS, чтобы сделать возможными пользовательские события прокрутки. Kendo UI Mobile включает в себя  пользовательский виджет прокрутки  и использует его для управления  виджетами на основе списка . Чтобы быть справедливым, эти платформы предлагают намного больше функциональности, чем простые события прокрутки, и пользовательский JavaScript обычно делается для достижения максимальной производительности,  но тот факт, что вам нужно перестроить прокрутку — основной принцип веб-браузера — для получить полезные события прокрутки на мобильном телефоне … безумие.

И имейте в виду, что мы не просто говорим о событии прокрутки. iOS <8 приостанавливает  все  выполнение JavaScript во время прокрутки. Поэтому любые интервалы, которые вы создаете  setInterval() , также приостанавливаются. Например, рассмотрим следующий код, который каждую секунду отображает новый номер:

var count = 0;
setInterval(function() {
    count++;
    document.body.innerHTML += "<p>" + count + "</p>";
}, 1000 );

В двух приведенных ниже рисунках я начинаю прокручивать после того, как счетчик достигает 3. Обратите внимание, что в iOS 7 (слева) счет останавливается во время прокрутки, тогда как в iOS 8 (справа) счет продолжается.

Пример приостановки выполнения JavaScript при прокрутке в iOS 7
Пример выполнения JavaScript при прокрутке в iOS 8

Таким образом, если вы по какой-либо причине используете интервалы в своих приложениях, они больше не будут произвольно приостановлены в iOS 8 во время прокрутки.

Обновление (25 сентября) : согласно 
комментарию Рика Байерса,  моя формулировка здесь неверна. iOS не приостанавливает выполнение JavaScript — она ​​приостанавливает рисование. Таким образом, JavaScript вашего приложения будет продолжать работать, но любые изменения в DOM не будут отображены до завершения действия прокрутки.

Как изменился веб

Обычно, когда конкретное поведение попадает в основной веб-браузер, мы застряли с ним до конца времени, но, к счастью, выполнение JavaScript во время прокрутки вышло из этой формы. Команда Android начала запуск событий непрерывной прокрутки в браузере по умолчанию, поставляемом с Ice Cream Sandwich, еще в 2011 году. Когда Chrome начал выпускать на Android 4.0, он также запускал события непрерывной прокрутки. Следующим браузером, который должен был измениться, был IE Mobile, который последовал примеру Windows Phone 8 еще в 2012 году.

Это сделало iOS единственной опорой, и с iOS 8 они присоединились к остальному мобильному миру, что, наконец, дает нам полный охват в мобильном Интернете.

Вы получаете события прокрутки.  Каждый получает события прокрутки.

Отсутствие приостановки выполнения JavaScript фактически добавляет некоторую совместимость для iOS, которой у них не было раньше. Например, популярный и забавный  плагин jQuery для scrollorama  начал работать корректно с iOS 8. На рисунке ниже он показан в действии.

scrollorama

Одно предостережение для разработчиков Cordova

Хотя Apple реализовала это изменение в iOS Safari, а также в своем новом  WKWebView элементе управления, она не изменила поведение прокрутки в своем старом  UIWebView элементе управления. И из-за  серьезной ошибки в WKWebView контроле замены  команда Cordova   пока не может перейти на WKWebViewновую версию  .

Это означает, что в настоящий момент приложения Cordova, работающие на iOS 8, продолжают приостанавливать выполнение JavaScript и будут продолжать, пока Cordova не сможет выполнить обновление. И это касается не только приложений Cordova. Любое приложение для iOS, которое использует веб-представления, включая Facebook, Twitter и Chrome для iOS, будет работать до тех пор, пока не обновит свои приложения WKWebView. Так что да, это означает, что вы можете получить различное поведение при открытии одного и того же URL-адреса из разных приложений iOS в зависимости от того, какой API они используют внутри.

Обновление (25 сентября) : комментатор Бен Кеннеди 
обнаружил,  что по какой-то безумной причине старое поведение прокрутки также применимо к веб-приложениям на домашнем экране. Подводя итог, можно сказать, что приложения, работающие в Safari или в 
WKWebView новом режиме прокрутки, приложения, работающие в 
UIWebView веб-приложении на домашнем экране или в домашнем экране, этого не делают.

Завершение

С iOS 8 это круто, что вы действительно можете выполнять код, пока пользователь выполняет прокрутку, и что эффекты параллакса теперь возможны без сложных хаков JavaScript, но для меня это круто, потому что Интернет действительно изменился. Все мобильные браузеры использовали для приостановки выполнения JavaScript при прокрутке, но со временем, по мере развития оборудования, они изменились, чтобы позволить JavaScript запускаться и запускать события прокрутки, как и ожидалось. Это дает мне надежду на то, что другие функции мобильного Интернета также могут  измениться к лучшему  .