Дабы лучше разобраться в JS, решил начать с примитивов. Первым что решил сделать это TODO. Вроде реализовать туду мне удалось, конечно наверняка собрав все самые детские грабли. Хотел бы получить комментарии с указанием на те самые грабли и возможно какие либо полезные советы, что бы держать вектор развития. Спасибо. Линк Вопросы: 1. Каким образом можно лучше организовать подписку элементов на события? 2. Почему в 80 строке if(row.classList.contains(elemClass)), в консоль пишет что у classList нету метода contains? Хотя он работает как надо. 3. Чем заменить forEach в findById? Подойдёт ли map или filter, но тогда придётся перезаписывать let todos, плохо это или хорошо?
1. Делегировано, отталкиваясь от родительского контейнера. 2. Работать может и правильно, но вопрос в том, с чем приходиться работать. Выведите в консоль row и посмотрите, что передаётся. 3. Из того, что возвращает ваша функция findById, вы используете только индекс элемента. Тогда эту функцию можно описать так: Код (Javascript): function findById(id) { return todos.findIndex(obj => obj.id === id); }
Как в jq с .on в строке 2 события можно или прокручивать на каждое событие надо? Код (Javascript): let App = document.querySelector('.todo'); App.addEventListener('click keypress', AppEvent); В посте выше я номером вопроса ошибся Открывал в доке этот метод, бегло прочитал и все равно forEach пихнул.
Можно и так сказать. Я не большой сторонник установки обработчика событий через свойство и тем более inline. Формирование списка (рендеринг) можно свести к подстановке значений с помощью литерального шаблона, а под каждое ожидаемое событие, создать свою делегированную обработку. Если очень схематически, то как-то так: Код (Javascript): const container = document.querySelector('.todo'), listBody = container.querySelector('.todo__body'); listBody.addEventListener('click', e => { if (e.target.tagName === 'A') { // Вызываем метод удаления пункта } }); listBody.addEventListener('change', e => { if (e.target.type === 'checkbox') { // Метод изменения статуса } }); listBody.addEventListener('blur', e => { if (e.target.contentEditable) { // Изменение текста } }, true); // ! Важен перехват события или использовать событие "input" container.addEventListener('keydown', e => { if (e.target.name === 'todo[create]' && e.which === 13) { // Добавляем пункт в список } }); function render() { let html = todos.map(el => ` <div class="todo__row" data-id="${el.id}"> <div class="todo__row-status"> <input name="todo[status]" type="checkbox" ${el.status ? 'checked' : ''}> </div> <div class="todo__row-title" contenteditable>${el.text}</div> <div class="todo__row-remove"> <a href="#remove">X</a> </div> </div>`); listBody.innerHTML = html.join(''); } render();
Так проще конечно чем создавать и аппендить элементы но с innerHTML могут быть XSS атаки тк тэги не эскейпятся и еще это медленнее.