导航菜单
  • 首页
  • 首页>万博manbext3.0首页登录集>JavaScript万博manbext3.0首页登录集

    用ES6写了一个todos,本地任务清单!

    学完了ES6,就可以拿一个小项目练练手,todoMVC是一个比较出名的用来练习各种编程语言的项目,可以直接去它官网看。

    这里写一个ES6版本的。

    4.jpg

    点击图片看效果,如果想看Vue2版本的,也可以点这里

    增删改查功能都有,自己看代码。

    核心代码:

    // 找对象
      const newTodoInput = $('.new-todo');
      const oTodoList = $('.todo-list');
      const oMain = $('.main');
      const oFooter = $('.footer');
      const oTodoCount = $('.todo-count');
      const oClearCompleted = $('.clear-completed');
      const oToggleAll = $('.toggle-all');
      const oTodoType = $$('.filters a');
    
      // 数据的本地存储
      const TODOS_KEY = 'dotos_ES6';
      let todosStorage = {
        get() {
          return JSON.parse(localStorage.getItem(TODOS_KEY)) || [];
        },
        set(todos) {
          localStorage.setItem(TODOS_KEY,JSON.stringify(todos));
        }
      }
      // 全局变量
      // 存储数据的todos
      // let todos = [
      //  { id: 1, title: '学习', completed: false },
      //  { id: 2, title: '做饭', completed: true },
      //  { id: 3, title: '接娃放学', completed: true },
      // ]
      let todos = todosStorage.get();
    
      // 用于区分单击和双击事件
      let timer = null;
    
      // 初始化渲染
      render(todos);
    
      // 当enter的时候添加事项
      newTodoInput.addEventListener('keyup', (e) => {
        if (e.key === 'Enter') {
          // 添加事项
          addTodo();
          todosStorage.set(todos);
          // 重新渲染
          render(todos);
        }
      })
    
      // 因为有很多事项,有很多删除按钮,所以用事件委托性能更高
      // ul同时委托了单击事件和双击事件,通过300ms的延迟来判断是单击还是双击
      // 如果300ms以后没有单击,则是单击事件,执行对应的代码。
      oTodoList.addEventListener('click', function (e) {
        clearTimeout(timer);
        timer = setTimeout(function () {
          const target = e.target;
          console.log(target);
          const tempLi = target.closest('li');
          // 根据li的id属性找到todos里面该id的数据,数字和字符串的相等用==
          const todo = todos.find(item => item.id == tempLi.id);
          // 如果点击的是删除按钮,则删除该事项
          if (target.className === 'destroy') {
            delTodo(todo);
          }
          // 如果点击的是复选框按钮,则切换完成和未完成的状态
          if (target.className === 'toggle') {
            todo.completed = target.checked;
          }
          // 修复双击下出现输入框编辑的时候,单击输入框的文本,输入框又消失的问题
          if (target.className === 'edit') {
            const oEditing = tempLi.querySelector('.edit');
            tempLi.classList.add('editing');
            oEditing.focus();
            return;
          }
          todosStorage.set(todos);
          render(todos);
    
        }, 300);
      })
    
      // 编辑事项
      oTodoList.addEventListener('dblclick', function (e) {
        // 如果300ms以内又有点击事件,则是双击事件,清掉前面定时器要执行的代码,执行双击对应的代码。
        clearTimeout(timer);
        const target = e.target;
        console.log(target);
        const tempLi = target.closest('li');
        const todo = todos.find(item => item.id == tempLi.id);
        if (target.tagName === 'LABEL') {
          const oEditing = tempLi.querySelector('.edit');
          tempLi.classList.add('editing');
          oEditing.focus();
          // 把输入框的光标放在最后面。
          // element.setSelectionRange(selectionStart, selectionEnd [, selectionDirection]);
          // 如果希望全选输入元素中的文本,你可以使用 HTMLInputElement.select() 方法。
          oEditing.setSelectionRange(-1, -1);
          // 存储输入框以前的数据
          const titleBeforeEdit = oEditing.value;
          oEditing.addEventListener('keyup', function (e) {
            console.log(e.key)
            const val = this.value.trim();
            // 编辑完成
            if (e.key === 'Enter') {
              if (val === '') {
                delTodo(todo);
              } else {
                todo.title = val;
              }
              todosStorage.set(todos);
              render(todos);
            }
            // 取消编辑
            if (e.key === 'Escape') {
              this.value = titleBeforeEdit;
              render(todos);
            }
          })
          // 失去焦点的时候,编辑完成
          oEditing.addEventListener('blur', function () {
            const val = this.value.trim();
            if (val === '') {
              delTodo(todo);
            } else {
              todo.title = val;
            }
            todosStorage.set(todos);
            render(todos);
          })
    
        }
      })
    
      // 删除完成的事项
      oClearCompleted.addEventListener('click', function () {
        todos = todos.filter(todo => !todo.completed);
        todosStorage.set(todos);
        render(todos);
      })
    
      // 点击全选复选框,对所有事项的状态切换
      oToggleAll.addEventListener('change', function () {
        const val = this.checked;
        for (const todo of todos) {
          todo.completed = val;
        }
        todosStorage.set(todos);
        render(todos);
      })
    
      // 根据hash切换a的状态
      // 不能点击a的时候获取hash,否则获取的是上一个hash值。
      window.onhashchange = function () {
        // console.log(location.hash);
        // a被选中的状态
        selectedType();
        render(todos);
      }
    
      // 找对象的函数
      function $(selector) {
        return document.querySelector(selector);
      }
    
      function $$(selector) {
        return document.querySelectorAll(selector);
      }
    
      // 渲染事项
      function render(todos) {
        // 对面板的切换
        if (todos.length) {
          oMain.style.display = 'block';
          oFooter.style.display = 'block';
        } else {
          oMain.style.display = 'none';
          oFooter.style.display = 'none';
        }
        if (!todos.length) {
          return;
        };
        let renderTodos = [];
        // 筛选数据
        // console.log(location.hash);
        switch (location.hash) {
          case '#/active':
            renderTodos = todos.filter(todo => !todo.completed);
            break;
          case '#/completed':
            renderTodos = todos.filter(todo => todo.completed);
            break;
          default:
            renderTodos = todos;
            break;
        }
        // a的被选中状态
        selectedType();
    
        let str = '';
        for (const obj of renderTodos) {
          str += `<li id='${obj.id}' class=${obj.completed ? 'completed' : ''}>
          <div class="view">
            <input class="toggle" type="checkbox" ${obj.completed ? 'checked' : ''}>
            <label>${obj.title}</label>
            <button class="destroy"></button>
          </div>
          <input class="edit" value="${obj.title}">
        </li>`
        }
        oTodoList.innerHTML = str;
    
        // 得到未完成的事项的个数。
        const remainingCount = getRemainingCount(todos);
    
        // 状态栏 未完成数量的显示
        oTodoCount.innerHTML = `<strong>${remainingCount}</strong> ${remainingCount === 1 ? 'item' : 'items'} left`
    
        // 删除完成事项的按钮
        // 如果事项的总个数大于未完成事项的个数,则按钮显示
        oClearCompleted.style.display = todos.length > remainingCount ? 'block' : 'none';
    
        //对全选复选框的状态设置
        if (remainingCount === 0 && todos.length !== 0) {
          oToggleAll.checked = true;
        } else {
          oToggleAll.checked = false;
        }
      }
    
      // 未完成的事项的个数
      function getRemainingCount(todos) {
        return todos.filter(item => !item.completed).length;
      }
    
    
      // 添加事项
      function addTodo() {
        let value = newTodoInput.value.trim();
        if (!value) return;
        todos.push({ id: Date.now(), title: value, completed: false });
        newTodoInput.value = '';
      }
      // 删除单个事项
      function delTodo(todo) {
        const index = todos.indexOf(todo);
        if (index !== -1) {
          todos.splice(index, 1);
        }
      }
    
      // 事项类别状态设置
      function selectedType() {
        oTodoType.forEach((item, index) => {
          if (item.hash === location.hash) {
            oTodoType.forEach(item => item.classList.remove('selected'));
            item.classList.add('selected');
            // console.log(item.hash);
          }
        })
      }


    点赞


    0
    保存到:

    相关文章

    发表评论:

    ◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

    Top