За последние 24 часа нас посетили 20852 программиста и 1700 роботов. Сейчас ищут 1406 программистов ...

Todo на native JS

Тема в разделе "JavaScript и AJAX", создана пользователем villiwalla, 10 авг 2018.

Метки:
  1. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Дабы лучше разобраться в JS, решил начать с примитивов. Первым что решил сделать это TODO. Вроде реализовать туду мне удалось, конечно наверняка собрав все самые детские грабли. Хотел бы получить комментарии с указанием на те самые грабли и возможно какие либо полезные советы, что бы держать вектор развития. Спасибо.

    Линк

    Вопросы:
    1. Каким образом можно лучше организовать подписку элементов на события?
    2. Почему в 80 строке if(row.classList.contains(elemClass)), в консоль пишет что у classList нету метода contains? Хотя он работает как надо.
    Снимок экрана от 2018-08-10 10-35-50.png
    3. Чем заменить forEach в findById? Подойдёт ли map или filter, но тогда придётся перезаписывать let todos, плохо это или хорошо?
     
  2. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    3-й вопрос решил, у меня был дубль события из-за не го был event, а не DOMTokenList
     
  3. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    1. Делегировано, отталкиваясь от родительского контейнера.
    2. Работать может и правильно, но вопрос в том, с чем приходиться работать. Выведите в консоль row и посмотрите, что передаётся.
    3. Из того, что возвращает ваша функция findById, вы используете только индекс элемента. Тогда эту функцию можно описать так:
    Код (Javascript):
    1. function findById(id) {
    2.   return todos.findIndex(obj => obj.id === id);
    3. }
     
  4. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Как в jq с .on в строке 2 события можно или прокручивать на каждое событие надо?
    Код (Javascript):
    1. let App = document.querySelector('.todo');
    2.      App.addEventListener('click keypress', AppEvent);
    В посте выше я номером вопроса ошибся :)

    Открывал в доке этот метод, бегло прочитал и все равно forEach пихнул.
     
  5. Deonis

    Deonis Старожил

    С нами с:
    15 фев 2013
    Сообщения:
    1.521
    Симпатии:
    504
    Можно и так сказать. Я не большой сторонник установки обработчика событий через свойство и тем более inline. Формирование списка (рендеринг) можно свести к подстановке значений с помощью литерального шаблона, а под каждое ожидаемое событие, создать свою делегированную обработку.
    Если очень схематически, то как-то так:
    Код (Javascript):
    1. const container = document.querySelector('.todo'),
    2.      listBody = container.querySelector('.todo__body');
    3.  
    4. listBody.addEventListener('click', e => {
    5.   if (e.target.tagName === 'A') {
    6.     // Вызываем метод удаления пункта
    7.   }
    8. });
    9. listBody.addEventListener('change', e => {
    10.   if (e.target.type === 'checkbox') {
    11.     // Метод изменения статуса
    12.   }
    13. });
    14. listBody.addEventListener('blur', e => {
    15.   if (e.target.contentEditable) {
    16.     // Изменение текста
    17.   }
    18. }, true); // ! Важен перехват события или использовать событие "input"
    19. container.addEventListener('keydown', e => {
    20.   if (e.target.name === 'todo[create]' && e.which === 13) {
    21.     // Добавляем пункт в список
    22.   }
    23. });
    24. function render() {
    25.   let html = todos.map(el => `
    26.   <div class="todo__row" data-id="${el.id}">
    27.       <div class="todo__row-status">
    28.         <input name="todo[status]" type="checkbox" ${el.status ? 'checked' : ''}>
    29.     </div>
    30.   <div class="todo__row-title" contenteditable>${el.text}</div>
    31.   <div class="todo__row-remove">
    32.       <a href="#remove">X</a>
    33.   </div>
    34.   </div>`);
    35.   listBody.innerHTML = html.join('');
    36. }
    37. render();
     
    villiwalla нравится это.
  6. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    Так проще конечно чем создавать и аппендить элементы но с innerHTML могут быть XSS атаки тк тэги не эскейпятся и еще это медленнее.
     
  7. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    @villiwalla Есть баг, если удалить все элементы а потом пытаться добавить то ошибка на 107 строке.
     
  8. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Действительно, http://jsfiddle.net/yanyshevvd/odj8quyp/