Сегодня при разработке мобильной страницы H5 я столкнулся с проблемой, что интерфейс не может вернуться в исходное положение при убрании клавиатуры на IOS. Проблемы и симптомы подробно описаны ниже:
Структура страницыРассматриваемая страница представляет собой структуру формы. То есть это похоже на структуру с четырьмя формами ввода под div, позволяющими пользователям заполнять почтовую информацию. похожий:
<div> <тип ввода=текстовый заполнитель=Пожалуйста, укажите провинцию, город и округ/> <тип ввода=текстовый заполнитель=Пожалуйста, заполните адрес/> <тип ввода=текстовый заполнитель=Пожалуйста, введите имя/> < тип ввода=текстовый заполнитель=Пожалуйста, введите адрес/контактный номер/></div>
Скриншот выглядит следующим образом:
Страница автоматически перемещается вверх при поднятии клавиатуры.Когда пользователь вводит контактный номер на мобильном телефоне, появляется клавиатура iPhone. В это время, чтобы пользователь мог видеть поле ввода телефона, вся страница на iPhone перемещается вверх (в противном случае клавиатура). закроет поле ввода телефона). В это время верхняя часть страницы фактически находится на некотором расстоянии от области просмотра (мы видим ряд полей ввода, исчезающих из интерфейса).
Страница не может быть восстановлена в исходное положение при закрытой клавиатуре.Однако когда пользователь завершает ввод и закрывает клавиатуру, хотя клавиатура убрана, положение страницы не будет восстановлено.
Анализ проблемыНа самом деле это вызвано неспособностью iOS предотвратить падение части страницы, прокручиваемой за пределы области просмотра, при втягивании клавиатуры. В это время пользователь может перетащить страницу пальцем обратно.
Но в конце концов этот опыт оказался не очень хорошим.
Чтобы решить эту проблему, мы можем вызвать window.scrollTo(0, 0) , когда пользовательский курсор покидает поле ввода, чтобы прокрутить страницу до ее выравнивания по верхней части области просмотра, тем самым достигая эффекта домашней страницы.
Итак, теперь проблема заключается в том, чтобы добавить события размытия во все четыре поля ввода формы, а затем вызвать window.scrollTo в обработчике. Однако независимо от того, добавляется ли он через @blur Vue или через операции DOM, необходимо добавить 4 прослушивателя событий, что не очень элегантно. Естественно, мы подумали об использовании прокси событий.
То есть мы помещаем прослушиватель событий в верхний элемент, а затем определяем функцию inputBlur для ожидания срабатывания;
<div @blur=inputBlur> <input type=text Placeholder=Пожалуйста, укажите провинцию, город и округ/> <input type=text Placeholder=Пожалуйста, заполните адрес/> <input type=text Placeholder=Пожалуйста, заполните name/> <input type=text Placeholder=Пожалуйста, введите свой контактный номер/></div>
В результате мы обнаружили, что наш прослушиватель событий не сработал. Причина в том, что событие blur поля ввода не может всплывать.
После запроса было обнаружено, что два события DOM: focus и blur не могут всплыть в спецификации. Аналогично этому, есть еще два события focusin и focusout которые могут всплывать.
В некоторых статьях в Интернете упоминается, что focusin и focusout — это события DOM, поддерживаемые только браузерами IE. Фактически, когда мы смотрим на документ MDN, мы обнаруживаем, что эти два события стали стандартом спецификации DOM 3 и поддерживаются большим количеством браузеров.
Поэтому, чтобы решительно решить проблему с помощью этих двух событий, мы изменили ее focusout
<div @focusout=inputBlur> <input type=text Placeholder=Пожалуйста, укажите провинцию, город и округ/> <input type=text Placeholder=Пожалуйста, заполните адрес/> <input type=text Placeholder=Пожалуйста, заполните name/> <input type=text Placeholder=Пожалуйста, введите свой контактный номер/></div>
Затем реализуем наш обработчик событий:
inputBlur(e) { // Сначала определяем, является ли целевой элемент, вызывающий событие, полем ввода. Мы фокусируемся только на поведении поля ввода. if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { window.scrollTo(0,0 } },На данный момент наша проблема решена. При вводе содержимого из поля ввода и последующем нажатии кнопки «Готово» на клавиатуре, чтобы закрыть клавиатуру, эффект соответствует нашим ожиданиям.
Однако после тестирования на мобильных телефонах мы обнаружили, что при переключении непосредственно с 电话输入框на 姓名输入框страница будет дрожать. Продолжим анализ.
На самом деле, причина, по которой два поля ввода дрожат при переключении, также очень проста. Потому что, когда мы переключаемся между двумя вышеуказанными полями ввода, страница сначала запускает событие blur 电话输入框, а затем запускает событие focus 姓名输入框. В этом случае, когда происходит размытие, будет срабатывать наш window.scrollTo(0,0) , вызывающий прокрутку страницы вниз, а затем 姓名输入框будет в фокусе, поэтому клавиатура будет продолжать всплывать --- это приведет к тому, что страница снова переместится вверх.
Фактически, при переключении между двумя полями ввода нам не нужно запускать поведение window.scrollTo , когда первое поле ввода размыто. Итак, давайте изменим наш код так, чтобы при выполнении операции переключения поля ввода поведение первого поля ввода можно было отключить. Здесь мы используем setTimeout для решения:
<div @focusout=inputBlur @focusin=inputFocus> <тип ввода=текстовый заполнитель=Пожалуйста, укажите провинцию, город и округ/> <тип ввода=текстовый заполнитель=Пожалуйста, заполните адрес/> <тип ввода=текстовый заполнитель= Пожалуйста, введите имя/> < input type=text Placeholder=Пожалуйста, введите свой контактный номер/></div>
inputBlur(e) { // Сначала определяем, является ли целевой элемент, вызывающий событие, полем ввода. Мы фокусируемся только на поведении поля ввода. if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') { // Поле ввода теряет фокус, и клавиатуру IOS необходимо вытолкнуть из прокрутив часть страницы, чтобы восстановить ее. Прокрутите страницу до верхней части окна и выровняйте ее console.log('set timer') this.timer = setTimeout(() => { console.log('timer Trigger') window.scrollTo(0,0); }, 0) } }, inputFocus(e) { // Если фокус, удалить таймер предыдущего поля ввода if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'input') {clearTimeout(this.timer } });Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.