Пользовательские события в JavaScript: полное руководство — Блог о самом интересном.

От создателя: события находятся всюду в веб-приложениях. От события DOMContentLoaded, которое запускается немедля, когда браузер завершает загрузку и анализирует HTML, до события unload, которое запускается конкретно перед тем, как юзер покидает ваш веб-сайт. Опыт использования веб-приложения, на самом деле, представляет собой просто серию событий. Для разрабов эти события помогают найти, что лишь что вышло в приложении, какое состояние юзера было в конкретное время и почти все другое.

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

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

Как сделать пользовательское событие в JavaScript

Внедрение конструктора событий

Внедрение конструктора CustomEvent

Отправка пользовательских событий в JavaScript

Как работают пользовательские события JavaScript?

Перетаскивание JavaScript

Как применять деструктуризацию объекта в JavaScript

Чтоб следовать этому управлению, вы обязаны иметь базисные познания о:

HTML и CSS

JavaScript и ES6

DOM и манипуляции с DOM

Давайте начнем!

Как сделать пользовательское событие в JavaScript

Пользовательские события можно создавать 2-мя методами:

Внедрение конструктора Event

Внедрение конструктора CustomEvent

Пользовательские события также могут быть сделаны при помощи document.createEvent, но большая часть способов предоставляемых объектом, возвращаемым из функции, устарели.

Внедрение конструктора Event

Пользовательское событие быть может сотворено при помощи конструктора Event, к примеру:

JavaScript const myEvent = new Event(‘myevent’, { bubbles: true, cancelable: true, composed: false

})

12345 const myEvent = new Event(‘myevent’, {  bubbles: true,  cancelable: true,  composed: false})

В приведенном выше фрагменте мы сделали событие myevent, передав имя события конструктору Event. Имена событий нечувствительны к регистру, потому myevent такое же, как myEvent и MyEvent и т.д. Конструктор события также воспринимает объект, который описывает некие принципиальные характеристики, касающиеся события.

bubbles

Свойство bubbles описывает, обязано ли событие распространяться ввысь к родительскому элементу. Установка значения true значит, что если событие отчаливает в дочернем элементе, родительский элемент может прослушивать событие и делать действие на его базе. Это поведение большинства нативных событий DOM, но для пользовательских событий по дефлоту установлено false.

Если вы желаете, чтоб событие отчаливало лишь определенному элементу, вы сможете приостановить распространение события при помощи event.stopPropagation(). Это обязано быть в оборотном вызове, который прослушивает событие. Подробнее о этом позднее.

cancelable

Как надо из наименования, cancelable показывает, обязано ли событие быть отменяемым. Нативные события DOM можно отменять по дефлоту, потому вы сможете вызывать event.preventDefault(), что предупредит действие события по дефлоту. Если для пользовательского события cancelable установлено значение false, при вызове event.preventDefault() не производится никаких действий.

composed

Свойство composed описывает, обязано ли это событие всплывать из теневого DOM (сделанные при использовании интернет — компонент) к реальному DOM. Если для bubbles установлено значение false, это не имеет значения, поэтому что вы очевидно указываете событию не всплывать ввысь. Но, если вы желаете выслать пользовательское событие в веб-компонент и прослушивать его на родительском элементе в настоящей модели DOM, то для скомпонованного характеристики нужно установить значение true.

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

Новое во Vue: Что ожидать во Vue 3

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

Внедрение конструктора CustomEvent

Пользовательское событие можно сделать при помощи конструктора CustomEvent:

JavaScript const myEvent = new CustomEvent(«myevent», { detail: {}, bubbles: true, cancelable: true, composed: false,

});

123456 const myEvent = new CustomEvent(«myevent», {  detail: {},  bubbles: true,  cancelable: true,  composed: false,});

Как показано выше, создание пользовательского события при помощи конструктора CustomEvent аналогично созданию события при помощи конструктора Event. Единственное отличие состоит в том, что объект передается в конструктор как 2-ой параметр.

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

Отправка пользовательских событий в JavaScript

Опосля сотворения событий у вас обязана быть возможность отправлять их. События могут быть высланы хоть какому расширяющемуся объекту EventTarget, и они включают в себя все элементы HTML, документ, окно и т.д. Вы сможете отправлять пользовательские события последующим образом:

JavaScript const myEvent = new CustomEvent(«myevent», { detail: {}, bubbles: true, cancelable: true, composed: false, });

document.querySelector(«#someElement»).dispatchEvent(myEvent);

1234567 const myEvent = new CustomEvent(«myevent», {  detail: {},  bubbles: true,  cancelable: true,  composed: false,});document.querySelector(«#someElement»).dispatchEvent(myEvent);

Чтоб прослушивать настраиваемое событие, добавьте прослушиватель событий к элементу, который вы желаете прослушивать, так же, как и с нативными событиями DOM.

JavaScript document.querySelector(«#someElement»).addEventListener(«myevent», (event) => { console.log(«I’m listening on a custom event»);

});

123 document.querySelector(«#someElement»).addEventListener(«myevent», (event) => {  console.log(«I’m listening on a custom event»);});

Как работают пользовательские события JavaScript?

Чтоб показать, как применять пользовательские события в приложении JavaScript, мы сделаем обычное приложение, которое дозволяет юзерам добавлять профиль и автоматом получать карточку профиля.

Создание пользовательского интерфейса

Сделайте папку, назовите ее как желаете и сделайте в папке файл index.html. Добавьте последующее в index.html:

Custom Events Application

Profile Card

Enter Profile Details

Drag an Image into this section or select an image Enter Name Enter Occupation

»» No Name Entered No Occupation Entered

1234567891011121314151617181920212223242526272829303132333435363738394041               Custom Events Application            

Profile Card

                  

Enter Profile Details

                  Drag an Image into this section or                      select an image                                                 Enter Name                                      Enter Occupation                                                  »»                No Name Entered        No Occupation Entered                

Тут мы добавляем разметку для странички. Страничка состоит из 2-ух разделов. 1-ый раздел — это форма, которая дозволяет юзеру созодать последующее:

Загрузить изображение при помощи перетаскивания либо вручную изберите файл изображения

Ввести имя

Ввести профессию

Данные, приобретенные из формы, будут отображаться во 2-м разделе — карточке профиля. 2-ой раздел просто содержит текст и изображения-заполнители. Данные, приобретенные из формы, перезапишут данные заполнителя содержимого. Сделайте файл style.css и заполните его последующим образом:

CSS * { box-sizing: border-box; } h1 { text-align: center; } main { display: flex; margin-top: 50px; justify-content: space-evenly; } .form { flex-basis: 500px; border: solid 1px #cccccc; padding: 10px 50px; box-shadow: 0 0 3px #cccccc; border-radius: 5px; } .form section { border: dashed 2px #aaaaaa; border-radius: 5px; box-shadow: 0 0 3px #aaaaaa; transition: all 0.2s; margin-bottom: 30px; padding: 50px; font-size: 1.1rem; } .form section:hover { box-shadow: 0 0 8px #aaaaaa; border-color: #888888; } .form section label { text-decoration: underline #000000; cursor: pointer; } .form-group { margin-bottom: 25px; } .form-group label { display: block; margin-bottom: 10px; } .form-group input { width: 100%; padding: 10px; border-radius: 5px; border: solid 1px #cccccc; box-shadow: 0 0 2px #cccccc; } #file-input { display: none; } .profile-card { flex-basis: 300px; border: solid 2px #cccccc; border-radius: 5px; box-shadow: 0 0 5px #cccccc; padding: 40px 35px; align-self: center; display: flex; flex-direction: column; justify-content: center; align-items: center; } .img-container { margin-bottom: 50px; } .img-container img { border-radius: 50%; width: 200px; height: 200px; } .profile-card .name { margin-bottom: 10px; font-size: 1.5rem; } .profile-card .occupation { font-size: 1.2rem;

}

Angular: Как создать полноэкранный календарь, такой как в Outlook

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 * {  box-sizing: border-box;}h1 {  text-align: center;}main {  display: flex;  margin-top: 50px;  justify-content: space-evenly;}.form {  flex-basis: 500px;  border: solid 1px #cccccc;  padding: 10px 50px;  box-shadow: 0 0 3px #cccccc;  border-radius: 5px;}.form section {  border: dashed 2px #aaaaaa;  border-radius: 5px;  box-shadow: 0 0 3px #aaaaaa;  transition: all 0.2s;  margin-bottom: 30px;  padding: 50px;  font-size: 1.1rem;}.form section:hover {  box-shadow: 0 0 8px #aaaaaa;  border-color: #888888;}.form section label {  text-decoration: underline #000000;  cursor: pointer;}.form-group {  margin-bottom: 25px;}.form-group label {  display: block;  margin-bottom: 10px;}.form-group input {  width: 100%;  padding: 10px;  border-radius: 5px;  border: solid 1px #cccccc;  box-shadow: 0 0 2px #cccccc;}#file-input {  display: none;}.profile-card {  flex-basis: 300px;  border: solid 2px #cccccc;  border-radius: 5px;  box-shadow: 0 0 5px #cccccc;  padding: 40px 35px;  align-self: center;  display: flex;  flex-direction: column;  justify-content: center;  align-items: center;}.img-container {  margin-bottom: 50px;}.img-container img {  border-radius: 50%;  width: 200px;  height: 200px;}.profile-card .name {  margin-bottom: 10px;  font-size: 1.5rem;}.profile-card .occupation {  font-size: 1.2rem;}

В конце концов, сделайте файл, чтоб вы могли добавить функциональность в приложение index.js.

Перетаскивание в JavaScript

1-ая функция, которую мы добавим в приложение, — это возможность загружать изображения. Для этого мы будем поддерживать перетаскивание, также загрузку вручную. Добавьте в файл JavaScript:

JavaScript const section = document.querySelector(«.form section»);

section.addEventListener(«dragover», handleDragOver); section.addEventListener(«dragenter», handleDragEnter);

section.addEventListener(«drop», handleDrop);

/** * @param {DragEvent} event */ function handleDragOver(event) { // Only allow files to be dropped here. if (!event.dataTransfer.types.includes(«Files»)) { return; } event.preventDefault(); // Specify Drop Effect. event.dataTransfer.dropEffect = «copy»;

}

/** * @param {DragEvent} event */ function handleDragEnter(event) { // Only allow files to be dropped here. if (!event.dataTransfer.types.includes(«Files»)) { return; } event.preventDefault();

}

/** * @param {DragEvent} event */ function handleDrop(event) { event.preventDefault(); // Get the first item here since we only want one image const file = event.dataTransfer.files[0]; // Check that file is an image. if (!file.type.startsWith(«image/»)) { alert(«Only image files are allowed.»); return; } handleFileUpload(file);

}

1234567891011121314151617181920212223242526272829303132333435363738394041424344 const section = document.querySelector(«.form section»); section.addEventListener(«dragover», handleDragOver);section.addEventListener(«dragenter», handleDragEnter);section.addEventListener(«drop», handleDrop); /** * @param {DragEvent} event */function handleDragOver(event) {  // Only allow files to be dropped here.  if (!event.dataTransfer.types.includes(«Files»)) {    return;  }  event.preventDefault();  // Specify Drop Effect.  event.dataTransfer.dropEffect = «copy»;} /** * @param {DragEvent} event */function handleDragEnter(event) {  // Only allow files to be dropped here.  if (!event.dataTransfer.types.includes(«Files»)) {    return;  }  event.preventDefault();} /** * @param {DragEvent} event */function handleDrop(event) {  event.preventDefault();  // Get the first item here since we only want one image  const file = event.dataTransfer.files[0];  // Check that file is an image.  if (!file.type.startsWith(«image/»)) {    alert(«Only image files are allowed.»);    return;  }  handleFileUpload(file);}

Тут мы избираем раздел из DOM. Это дозволяет прослушивать надлежащие события, которые нужны для обеспечения операции перетаскивания — а конкретно dragover, dragenter и drop.

В функции handleDragOver мы гарантируем, что перетаскиваемый элемент является файлом, и устанавливаем эффект перетаскивания на copy. handleDragEnter также делает аналогичную функцию, гарантируя, что мы обрабатываем лишь перетаскивание файлов.

Фактическая функциональность реализуется, когда файл удаляется, и мы обрабатываем это при помощи handleDrop. Во-1-х, мы предотвратим действие браузера по дефлоту, которое заключается в открытии файла перед его доставкой.

Мы подтверждаем, что файл является изображением. Если это не так, мы отправляем сообщение о ошибке, чтоб юзер знал, что мы принимаем лишь файлы изображений. Если проверка прошла удачно, мы перебегаем к обработке файла в функции handleFileUpload, которую сделаем дальше. Обновите index.js:

JavaScript /** * @param {File} file */ function handleFileUpload(file) { const fileReader = new FileReader(); fileReader.addEventListener(«load», (event) => { // Dispatch an event to the profile card containing the updated profile. dispatchCardEvent({ image: event.target.result, }); }); fileReader.readAsDataURL(file);

}

const profileCard = document.querySelector(«.profile-card»);
const CARD_UPDATE_EVENT_NAME = «cardupdate»;

function dispatchCardEvent(data) { profileCard.dispatchEvent( new CustomEvent(CARD_UPDATE_EVENT_NAME, { detail: data, }) );

}

123456789101112131415161718192021222324 /** * @param {File} file */function handleFileUpload(file) {  const fileReader = new FileReader();  fileReader.addEventListener(«load», (event) => {    // Dispatch an event to the profile card containing the updated profile.    dispatchCardEvent({      image: event.target.result,    });  });  fileReader.readAsDataURL(file);} const profileCard = document.querySelector(«.profile-card»);const CARD_UPDATE_EVENT_NAME = «cardupdate»; function dispatchCardEvent(data) {  profileCard.dispatchEvent(    new CustomEvent(CARD_UPDATE_EVENT_NAME, {      detail: data,    })  );}

Мобильное приложение VK научилось продвигать бизнес-страницы

Функция handleFileUpload воспринимает файл в качестве параметра и пробует прочесть файл в качестве URL данных при помощи устройства чтения файла.

Конструктор FileReader простирается от EventTarget, что дозволяет прослушивать события. Событие load запускается опосля загрузки изображения — в нашем случае как URL-адрес данных.

Вы также сможете загружать изображения в остальных форматах. На MDN есть хорошая документация по FileReader API, если вы желаете выяснить больше о считывании файлов.

Опосля загрузки изображения нам нужно показать его в карточке профиля. Для этого мы отправим настраиваемое событие cardupdate в карточку профиля. dispatchCardEvent обрабатывает создание и отправку события в карточку профиля.

Если вы помните из раздела выше, у пользовательских событий есть свойство detail, которое можно применять для передачи данных. В этом случае мы передаем объект, содержащий URL-адрес изображения, приобретенный от программки чтения файлов.

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

JavaScript profileCard.addEventListener(CARD_UPDATE_EVENT_NAME, handleCardUpdate); /** * @param {CustomEvent} event */ function handleCardUpdate(event) { const { image } = event.detail; if (image) { profileCard.querySelector(«img»).src = image; }

}

12345678910 profileCard.addEventListener(CARD_UPDATE_EVENT_NAME, handleCardUpdate);/** * @param {CustomEvent} event */function handleCardUpdate(event) {  const { image } = event.detail;  if (image) {    profileCard.querySelector(«img»).src = image;  }}

Как показано выше, вы просто добавляете прослушиватель событий, как обычно, и вызываете функцию handleCardUpdate, когда событие запускается.

Как применять деструктуризацию объекта в JavaScript

handleCardUpdate получает событие как параметр. Используя деструктуризацию объекта, вы сможете получить свойство image из event.detail. Потом установите атрибут изображения src в карточке профиля как URL-адрес изображения, приобретенный из события. Чтоб разрешить юзерам загружать изображения через поле ввода:

JavaScript const fileInput = document.querySelector(«#file-input»);

fileInput.addEventListener(«change», (event) => { handleFileUpload(event.target.files[0]);

});

12345 const fileInput = document.querySelector(«#file-input»); fileInput.addEventListener(«change», (event) => {  handleFileUpload(event.target.files[0]);});

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

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

Последующая функция, которую необходимо добавить — это обновление имени и профессии:

JavaScript const nameInput = document.querySelector(«#name»);

const occupationInput = document.querySelector(«#occupation»);

occupationInput.addEventListener(«change», (event) => { dispatchCardEvent({ occupation: event.target.value, }); }); nameInput.addEventListener(«change», (event) => { dispatchCardEvent({ name: event.target.value, });

});

12345678910111213 const nameInput = document.querySelector(«#name»);const occupationInput = document.querySelector(«#occupation»); occupationInput.addEventListener(«change», (event) => {  dispatchCardEvent({    occupation: event.target.value,  });});nameInput.addEventListener(«change», (event) => {  dispatchCardEvent({    name: event.target.value,  });});

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

JavaScript /** * @param {CustomEvent} event */ function handleCardUpdate(event) { const { image, name, occupation } = event.detail; if (image) { profileCard.querySelector(«img»).src = image; } if (name) { profileCard.querySelector(«span.name»).textContent = name; } if (occupation) { profileCard.querySelector(«span.occupation»).textContent = occupation; }

}

123456789101112131415 /** * @param {CustomEvent} event */function handleCardUpdate(event) {  const { image, name, occupation } = event.detail;  if (image) {    profileCard.querySelector(«img»).src = image;  }  if (name) {    profileCard.querySelector(«span.name»).textContent = name;  }  if (occupation) {    profileCard.querySelector(«span.occupation»).textContent = occupation;  }}

Обновите функцию handleCardUpdate, чтоб она смотрелась как в приведенном выше фрагменте. Тут мы опять используем деструктуризацию объекта, чтоб получить изображение, имя и род занятий из event.detail. Опосля получения данных мы отображаем их на карточке профиля.

Заключение

Время от времени легче осознать код, когда вы думаете о нем исходя из убеждений отправляемых событий — как пользовательских, так и нативных событий DOM. Пользовательские события JavaScript могут сделать лучше взаимодействие с юзером вашего приложения при правильном использовании. Потому логично, что они включены в некие из ведущих фреймворков JavaScript, таковых как Vue.js (во Vue вы отправляете пользовательские события при помощи $emit). Код демонстрации, использованный в этом руководстве, доступен на GitHub.

Создатель: James James

Редакция: Команда webformyself.

Источник

Вам также может понравиться