На прошлой неделе я работал над небольшим приложением со списком дел в качестве еженедельного проекта для BootCamp для веб-разработчиков, в котором я зарегистрирован. Приложение построено с использованием ванильного JavaScript, HTML/CSS для пользовательского интерфейса. Хотя приложение со списком дел обязательно должно быть в портфолио разработчиков интерфейса, я никогда не делал этого до этого проекта, и теперь я понимаю, почему люди говорят, насколько важно это для применения ваших навыков. на практике.

Функции приложения были понятными и, казалось бы, простыми:

  1. Отображать элементы списка динамически
  2. Сохраните данные в локальном хранилище
  3. Пользователь должен иметь возможность добавлять/удалять элементы в/из списка
  4. Пользователь должен иметь возможность редактировать элементы списка

Как вы можете видеть в приведенном выше коде, я использовал ‹input type="text"› для отображения описания (имени) каждой задачи. Причина, по которой я решил использовать его, заключается в возможности редактирования описания и прослушивания события change.

В процессе создания приложения я не сталкивался с какими-либо проблемами, пока не начал работать с событиями focusin и focusout наряду с событиями click.

Это был мой мыслительный процесс, создающий эту функцию:

  1. Прикрепите прослушиватель событий focusin к полю ввода.
  2. Применение стилей (путем добавления классов)
  3. Скрыть кнопку параметров и отобразить кнопку удаления (отображать: нет и отображать: заблокировать).
  4. При событии focusout все возвращается на круги своя.
  5. Прикрепите прослушиватель событий кликов к кнопкам удаления
  6. Удалите выбранный элемент (сопоставьте атрибут data-index со свойством index объекта элемента в нашем списке), затем сохраните и отобразите новый список.

Режим редактирования работал как положено. Как видите, стили применяются, и кнопка отображается, когда я перехожу в режим редактирования. И наоборот, когда я выхожу из фокуса ввода (щелкаю в любом другом месте документа), элементы списка переходят в исходное состояние.

Теперь вот где проблема имеет место

Как я уже говорил, мы устанавливаем для кнопки удаления значение display: none в focusout, что удаляет ее из DOM. Когда мы попытаемся нажать на эту кнопку, сработает событие focusout и удалит элемент, не оставив нам возможности щелкнуть по нему и, следовательно, удалить список элементов. Так как же нам обойти эту ошибку?

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

Если бы это было событие щелчка, мы знаем, что могли бы использовать ClickEvent.target для получения элемента, на который мы нажали. Однако событие Focusout отличается. Он не слушает щелчки, но срабатывает всякий раз, когда мы выходим из фокуса элемента, к которому привязано событие.

Записывая свойство события, я заметил, что ключ relatedTarget и его значение — это элемент, на который мы нажимаем.

Когда мы нажимаем на пустое место в документе, мы получаем null в качестве значения, но если это элемент, значением является элемент, на который мы нажимаем.

Отсюда мы добавляем нашу проверку, чтобы увидеть, содержит ли выбранный элемент класс «btn-delete», и мы ничего не делаем, если он есть (return), в противном случае мы просто скрываем кнопку. Вот как в итоге будет выглядеть наш обработчик событий.

Виола! Ошибка была исправлена. Наше приложение со списком дел теперь выглядит намного лучше и чище, и мы можем делать с ним все, что захотим.