кому не лень, поделитесь опытом по javascript
Решил я вот в одной из своих программ избавиться от jquery
Его там реально 4 строчки и нет смысла его тянуть.
Но что то я туплю.
У меня был некий обработчик события change у формы
Работает как нужно — события изменения любого элемента этой формы запускают этот код и что важно — this всегда ссылается на форму. Что позволяет следующей строкой получить в переменную все значения всех элементов формы, неважно какой именно был изменен.
Начинаю разбираться с событиями в javascript.
Опираюсь на это learn.javascript.ru/introduction-browser-events
и там описывается три способа создать реакцию на событие.
Пишу вот такое
Так как же правильно обработать событие change чтобы в идеале event.target указывавал на форму в которой произошло измеенние, а не на сам элемент или хотя бы, а как грамотные люди определяют в какой форме на странице произошло изменение?
Его там реально 4 строчки и нет смысла его тянуть.
Но что то я туплю.
У меня был некий обработчик события change у формы
$(document).on('change', this.config.filterWrapper, function () {
const filterData = $(this).serializeArray();
}
где this.config.filterWrapper это идентификатор формы.Работает как нужно — события изменения любого элемента этой формы запускают этот код и что важно — this всегда ссылается на форму. Что позволяет следующей строкой получить в переменную все значения всех элементов формы, неважно какой именно был изменен.
Начинаю разбираться с событиями в javascript.
Опираюсь на это learn.javascript.ru/introduction-browser-events
и там описывается три способа создать реакцию на событие.
Есть три способа назначения обработчиков событий:Ну работать с инлайновым js и вписывать его в html не солидно, путаюсь понять работу addEventListener.
Атрибут HTML: onclick="...".
DOM-свойство: elem.onclick = function.
Специальные методы: elem.addEventListener(event, handler[, phase]) для добавления, removeEventListener для удаления.
Пишу вот такое
document.addEventListener('change', function (event) {
console.log(event.target);
})
смущает тот факт, что отслеживаются все события change возникающие в документе (подозреваю что jquery работает под капотом так же просто это скрыто от нас). Но проблема на лицо — как отслеживать события только внутри определенной формы? На странице может быть их много. Приходит в голову мысль, что раз у нас есть объект event то через него можно проверять кто инициатор, кто target и уже по условию проверять наш ли это пациент. Но ожидаемо, что targеt это не есть форма, это dom элемент, на котором произошло событие — input, select и так далее. А значит мне по прежнему ничего не известно о том, из какой конкретно формы этот элемент. Да можно пытаться у каждого элемента проверять кто его предок, проверять у предка id и смотреть не наша ли это форма, но это плохо и плюс формы на всегда содержит только тег form и сразу inputы, там может быть сложная разметка div, span что угодно.Так как же правильно обработать событие change чтобы в идеале event.target указывавал на форму в которой произошло измеенние, а не на сам элемент или хотя бы, а как грамотные люди определяют в какой форме на странице произошло изменение?
Комментарии: 16
а я дурак. наверное же вместо document addEventListener можно назначить на заранее полученный элемент.
что-то переделка всего 4 строк с jquery на синтаксис javascript дается тяжко)
А что нет никакого метода для получения данных из формы?
Я вот для себя открыл, что оказывается существует некая коллекция форм
learn.javascript.ru/form-elements
которая содержит в себе все формы, все элементы всех форм и так далее
Могу делать цикл, сам создавать сам объекты и наполнить ими какой-то массив. Но тогда нужно еще и проверять какой элемент выбран (например если есть input type radio), ну тоесть я то нагорожу 30 строчек кода). Но может я просто не нашел удобного метода в языке js для работы с данными с формы?
А что нет никакого метода для получения данных из формы?
.serializeArray();
давал мне массив объектов в виде name — value0: Object { name: "price", value: "22000" }
1: Object { name: "price", value: "150000" }
2: Object { name: "brand", value: "Maugli" }
length: 3
а javascript не подскажите, имеет метод получения сразу всех заполненных полей формы?Я вот для себя открыл, что оказывается существует некая коллекция форм
learn.javascript.ru/form-elements
которая содержит в себе все формы, все элементы всех форм и так далее
Могу делать цикл, сам создавать сам объекты и наполнить ими какой-то массив. Но тогда нужно еще и проверять какой элемент выбран (например если есть input type radio), ну тоесть я то нагорожу 30 строчек кода). Но может я просто не нашел удобного метода в языке js для работы с данными с формы?
Спасибо, но formdata он вроде для отправки форм. я смотрел на него, не подходит (или я не умею его готовить)
Очень удобным для меня открытием оказались коллекции данных js — form
learn.javascript.ru/form-elements
сделал пока некий метод на них, но не уверен что смог учесть все нюансы. В форме могут содержаться элементы разных типов. Так например у инпутов нужно получать value, у textarea получать innerHtml, checkbox нужно проверять на наличие атрибута checked и так далее и это чтобы получить то, что мне давала даже не одна строка, а одно слово в jquery — serializeArray()
Очень удобным для меня открытием оказались коллекции данных js — form
learn.javascript.ru/form-elements
сделал пока некий метод на них, но не уверен что смог учесть все нюансы. В форме могут содержаться элементы разных типов. Так например у инпутов нужно получать value, у textarea получать innerHtml, checkbox нужно проверять на наличие атрибута checked и так далее и это чтобы получить то, что мне давала даже не одна строка, а одно слово в jquery — serializeArray()
Сорри, прочитал наискосок, не вник.
Заменить serializeArray одной строкой не получится. Вот люди предлагают свой вариант замены.
Заменить serializeArray одной строкой не получится. Вот люди предлагают свой вариант замены.
надо же, это примерно то, что придумал и я в своем методе.
спасибо за подсказки.
спасибо за подсказки.
а насчет fetch, да штука классная. Но это уже обработка запросов.
А у меня другое. Я наверное запутал всех, акцентируя внимание на слове — форма.
Это некий фильтр и в момент изменения любого его поля нужно собрать все текущие данные в виде массива объектов. Теоретически это может быть и вовсе не форма, а какие-то дивы. Ведь форма никогда и не отправляется по сути. Отслеживается событие change, все данные (выбранные чекбоксы например) собираются и далее уже пошла логика работы с этими данными. Форма здесь скорее дань традициям.
А у меня другое. Я наверное запутал всех, акцентируя внимание на слове — форма.
Это некий фильтр и в момент изменения любого его поля нужно собрать все текущие данные в виде массива объектов. Теоретически это может быть и вовсе не форма, а какие-то дивы. Ведь форма никогда и не отправляется по сути. Отслеживается событие change, все данные (выбранные чекбоксы например) собираются и далее уже пошла логика работы с этими данными. Форма здесь скорее дань традициям.
Хорошая практика — вешать обработчик на document, а затем разруливать его таргет через обычный if.
Если тебе нужно отслеживать изменения внутри какой-то конкретной формы, то просто проверяешь ее наличие среди родителей через closest.
Данные из формы удобнее всего собирать через FormData, как уже выше сказали. Иногда может потребоваться дополнительная обработка всяких чекбоксов, потому что по умолчанию неотмеченные чекбоксы вообще не собираются, например.
К слову, FormData — итерируемый объект, поэтому ты можешь легко по нему пройтись через цикл и поменять то, что тебе нужно:
fetch лично мне не зашел, слишком много телодвижений требуется для обычных ajax-запросов. Чтобы принять json на сервере, нужно лезть в php://input и оттуда его доставать, что может быть не всегда удобно по разным причинам. Тут либо написать свой простенький асинхронный метод-обертку для запросов, который будет построен на старом XMLHttpRequest, либо посылать данные в multipart/form-data, тогда проблем не будет.
Помимо этого, fetch до сих пор не умеет отслеживать прогресс загрузки, поэтому если нужна такая фича, можно смело от него отказываться.
document.addEventListener('change', e => {
const target = e.target;
if (target.matches('.some-selector')) { /* code */}
// или можно прям на наличие класса проверять
if (target.classList.contains('имя класса без точки')) { /* code */ }
});
Если тебе нужно отслеживать изменения внутри какой-то конкретной формы, то просто проверяешь ее наличие среди родителей через closest.
if (target.closest('.form') !== null) {}
Данные из формы удобнее всего собирать через FormData, как уже выше сказали. Иногда может потребоваться дополнительная обработка всяких чекбоксов, потому что по умолчанию неотмеченные чекбоксы вообще не собираются, например.
К слову, FormData — итерируемый объект, поэтому ты можешь легко по нему пройтись через цикл и поменять то, что тебе нужно:
for (const [key, value] of formDataInstance) {
console.log(key, value);
}
fetch лично мне не зашел, слишком много телодвижений требуется для обычных ajax-запросов. Чтобы принять json на сервере, нужно лезть в php://input и оттуда его доставать, что может быть не всегда удобно по разным причинам. Тут либо написать свой простенький асинхронный метод-обертку для запросов, который будет построен на старом XMLHttpRequest, либо посылать данные в multipart/form-data, тогда проблем не будет.
Помимо этого, fetch до сих пор не умеет отслеживать прогресс загрузки, поэтому если нужна такая фича, можно смело от него отказываться.
Хорошая практика — вешать обработчик на document, а затем разруливать его таргет через обычный if.ну да, я вначале так и пробовал,
Приходит в голову мысль, что раз у нас есть объект event то через него можно проверять кто инициатор, кто target и уже по условию проверять наш ли это пациент.но для меня проблемой стало то, что таргет как ему и положено всегда указывает на инициатора события, тоесть на input например, если мы изменили текст в нем. Но как определить, что этот инпут именно из той формы, за которой мы хотим следить?
К примеру форма имеет атрибут id = «filter», но на странице есть еще 20 форм, формы заказа обратного звонка, калькулятора какого-то, еще что то.
если наш листенер повешен на весь объект документ, то он будет следить за всеми элементами всех форм и единственный способ решить задачу, который я вижу, это всем input задавать определенный класс и проверять на его наличие.
Пока сделал так
let form = document.getElementById('formtest');
form.addEventListener('change', function (event) {}
по крайней мере под мою задачу так оказалось удобнее. теперь событие возникает только если изменена конкретная форма и что важно для меня — target тоже всегда сама форма, а нее ее отдельный инпут.Насчет FormData нужно будет присмотреться. Я использовал ее несколько раз, но когда нужно было подготовить данные для отправки ajax-ом (хотя это можно сделать и вручную если заранее знаешь какие в форме input и их названия), я чаще пользовался formData чтобы передать через ajax файл. Но наверное вы и Сергей правы — собирать данные из формы эта штука должна уметь.
Но как определить, что этот инпут именно из той формы, за которой мы хотим следить?Опять же, через closest.
Он поднимается вверх по DOM и ищет указанного родителя.
У тебя может быть хоть 150 одинаковых форм, но измененный инпут принадлежит только одной из них.
Поэтому ты делаешь, например, вот так
if (target.closest('.formClass') !== null) {}
и узнаешь, что измененный инпут принадлежит форме с классом formClass.Более того, ты можешь сразу сохранить эту форму в переменную и в дальнейшем работать с ней, если есть такая необходимость.
const form = target.closest('.formClass');
if (form !== null) {}
если наш листенер повешен на весь объект документ, то он будет следить за всеми элементами всех форм и единственный способ решить задачу, который я вижу, это всем input задавать определенный класс и проверять на его наличие.Верно, он будет следить за всеми элементами всех форм, в этом и есть его плюс, который называется делегирование.
Например, если у тебя на странице появятся еще 2 формы с таким же классом, то они автоматически подхватятся и в них тоже будут отслеживаться изменения.
И нет, не нужно задавать всем инпутам определенный класс.
Твоя задача
let form = document.getElementById('formtest');
form.addEventListener('change', function (event) {}
решается вот такdocument.addEventListener('change', e => {
const target = e.target;
if (target.closest('#formtest') !== null) {}
});
Это будет точно так же срабатывать, если изменения происходят только в рамках конкретной формы.Твоя форма может быть присвоена переменной, как я уже показал выше, чтобы ты мог с ней работать и собирать из нее данные через FormData, например.
К слову, getElementById('formtest') уже практически не используется в новом коде, поэтому рекомендую заменять его на querySelector('#formtest').
К слову, getElementById('formtest') уже практически не используется в новом коде, поэтому рекомендую заменять его на querySelector('#formtest').А почему не используется? getElementById быстрее находит элемент, чем querySelector
querySelector настолько быстрый, что нет никакого смысла юзать getElementById ради скорости. В реальных сценариях в 99.9% случаев между ними не будет никакой разницы, потому что ощутить ее можно только при десятках тысяч операций. Более того, querySelector(All) — универсальный, поэтому можно ограничиться только им для всех сценариев, что в целом сделает твой код чуточку читабельнее.
Артем, а подскажите, откуда вы брали информацию о методах у target? Да и на сколько я понимаю, это применимо к любому dom-элементу.
matches
classList
closest
Просто это очень похоже на методы jquery а вот у ванильного js я нигде не находил их описания.
максимум
learn.javascript.ru/dom-navigation
но там эти методы не перечислены.
matches
classList
closest
Просто это очень похоже на методы jquery а вот у ванильного js я нигде не находил их описания.
максимум
learn.javascript.ru/dom-navigation
но там эти методы не перечислены.
Например, вот тут они достаточно хорошо описаны.
Практически всю нужную тебе инфу можно смотреть в рамках этого сайта. Просто пишешь прямо там в поиске нужный метод или фразу, а потом смотришь результаты.
Практически всю нужную тебе инфу можно смотреть в рамках этого сайта. Просто пишешь прямо там в поиске нужный метод или фразу, а потом смотришь результаты.
А какой смысл отказа? Завтра еще что-то понадобится дописать, и опять писать кучу кода. А jq на каждом втором сайте, и он скорее всего уже у юзера в кэше лежит, если юзать ссылку на публичный cdn.
В целом я с вами согласен. То что я пишу сейчас — это не кому-то на заказ, а просто для саморазвития, поэтому творю что хочу)
Я когда начинаю что то разрабатывать совсем с нуля, иду от простого к сложного, сначала делаю наброски, пишу так как легче мне и проверяю саму идею. Если уже заработало и идея жизнеспособна, начинаю как-то код улучшать. Поэтому наброски как правило (если код использует js ) делаю на jquery.
А на днях посмотрел, ну реально же всего 4 места где используется jquery (а тут еще месяцок назад на этом сайте под одним постом была долгая дискуссия, мол что js сейчас сам по себе идеален для работы c DOM) и стало интересно смогу или нет избавиться от него, просто для прокачки навыков скорее всего.
Я когда начинаю что то разрабатывать совсем с нуля, иду от простого к сложного, сначала делаю наброски, пишу так как легче мне и проверяю саму идею. Если уже заработало и идея жизнеспособна, начинаю как-то код улучшать. Поэтому наброски как правило (если код использует js ) делаю на jquery.
А на днях посмотрел, ну реально же всего 4 места где используется jquery (а тут еще месяцок назад на этом сайте под одним постом была долгая дискуссия, мол что js сейчас сам по себе идеален для работы c DOM) и стало интересно смогу или нет избавиться от него, просто для прокачки навыков скорее всего.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.