На этой неделе я узнал кое-что новое о DOM API, а именно, как создавать и потреблять пользовательские события. Представьте себе, что вместо того, чтобы слушать событие щелчка мыши, вы создаете свое собственное событие, которое нужно слушать! Звучит круто, правда? Позвольте мне рассказать вам об этой интересной возможности, о которой я даже не знал, пока использовал слушатели событий.
Я создал проект, чтобы проиллюстрировать одно из возможных применений использования пользовательских событий. Например, я хочу прослушать заказ в кухонной системе, чтобы повара знали, что будет дальше, а затем вывести этот заказ на экран. Я смоделировал это в проекте на github.
// fetch data from api using netlify functions
const fetchData = async () => {
//get the data from my super secret netlify function
const res = await fetch(`/.netlify/functions/token-hider`)
//if something goes wrong, throw an error
if (!res.ok) {
throw new Error(`http response: ${res.status}`)
}
// if something goes right, save the json response
const getMeals = await res.json();
// pass the fetched data to a new function to process
processOrder(getMeals)
}
Мы начинаем наше путешествие со стандартного получения данных, я использую netlify cli, чтобы скрыть свой ключ API, который я купил за 2 доллара в месяц, но для тех из вас, кто не хочет его покупать, бесплатный api можно найти здесь. Основная работа в этой программе происходит после передачи полученных данных в функцию для обработки данных в наши собственные события, которые мы производим из экологически чистых, органических и этически чистых продуктов.
// This function is called to get a random selection of meals from the array passed in from fetch
const processOrder = (getMeals) => {
//save an array of randomly selected meals
const mealsData = getMeals.meals
// select a random number of meals starting from the beginning of the mealsData array
// at least one, up to the length of the array given.
const customerOrder = mealsData.slice(0, Math.floor(Math.random() * mealsData.length) + 1)
// map an array of objects
const orderDetails = customerOrder.map(item => (
{
mealName: item.strMeal,
mealImg: item.strMealThumb
}
))
// create and initialize event.
var orderEvent = new CustomEvent(
'order',
{ detail: orderDetails }
);
// tell the browser api to fire the event
window.dispatchEvent(orderEvent)
}
const stopMe = setInterval(fetchData, 2000);
Сначала возьмем случайное число записей из массива данных и создадим массив объектов, сохранив название блюда и изображение. Для следующего трюка мы создадим и инициализируем пользовательское событие, используя синтаксис
var orderEvent = new CustomEvent('whatever name you want to call the event', { detail: data-you-want-to-pass }
После этого мы запускаем событие с помощью window.dispatchEvent(variable-you-saved-custom-event-to).
Моя первоначальная идея для этого проекта заключалась в том, чтобы иметь случайный интервал времени для запуска события, но я еще не придумал, как вставить случайный интервал времени в функцию setInterval, поэтому пока я установил его равным двум секундам. Каждые две секунды я вызываю функцию fetchData, которая вызывает функцию processOrder, запускающую событие order. Вы потребляете событие заказа, как любое другое встроенное событие из API браузера. Событие order было отправлено в интерфейс окна, поэтому мы добавляем слушателя события в интерфейс окна, а затем функцию обратного вызова для обработки данных с помощью event.detail (помните, как мы устанавливали, что мы получим из detail при инициализации пользовательского события).
window.addEventListener('order', (evt) => {
let root = document.getElementById('root');
const section = document.createElement('section');
let orderNumber = document.createElement('p')
section.className = 'order-container'
orderNumber.className = 'order-number'
orderNumber.innerText = `Order ${Math.floor(Math.random() * 1000)}`
section.append(orderNumber)
const displayOrder = evt.detail.map(item => {
const p = document.createElement('p')
const img = document.createElement('img')
const div = document.createElement('div')
div.className = 'item-in-order'
img.src = `${item.mealImg}/preview`
img.alt = item.mealName
p.innerText = item.mealName
div.append(p)
div.append(img)
return div
})
displayOrder.forEach(item => {
section.append(item)
})
root.append(section)
})
Поместите эти данные в DOM, и вы получите что-то вроде этого
Вот и все! Я хотел поделиться этими знаниями, поскольку я не знал этого во время онлайн-оценки в компании мечты, и хотел восполнить этот пробел. Лучший способ узнать что-то — это объяснить это кому-то другому, и я надеюсь, что мое объяснение было простым и понятным, если нет, пожалуйста, дайте мне знать, как я могу улучшить!