尝试为 Javascript 中的待办事项列表应用程序做一个过滤器,但苦苦挣扎

Trying to do a filter for a to-do list app in Javascript but struggling

我有一个待办事项列表,它工作得很好,但我正在尝试过滤它,但我有点吃力。 基本上,每个任务都是一个对象,每个对象都有 text、id 和 checked 属性。 例如,我想只显示在我按“激活”时未选中的任务。

希望对你有所帮助。 这是一张图片以供更多说明:


/*  Selectors  */
const switcher = document.querySelector(' input[Type="checkbox"]');
const body = document.body;
const formT = document.querySelector(`[data-new-todo-form]`)
const inputT = document.querySelector(`[data-new-todo-input]`)
const todoList = document.getElementById('todo-list');
const filterList = document.querySelector('.controls-list')

/* array that holds tasks */
let tasks = [];


/*  EVENT LISTENERS */
switcher.addEventListener('change', (e) => {
    if(e.target.checked) {
        body.classList.replace('light', 'dark')
    } else {
        body.classList.replace('dark', 'light')
    }

})


formT.addEventListener('submit', e => {
    e.preventDefault()
    
    let text = inputT.value.trim();
    if(text !== '') {
       addTask(text);
       inputT.value = '';
       inputT.focus();

    } 
 
})


todoList.addEventListener('click', e => {
    if (e.target.classList.contains('js-tick')) {
        const itemKey = e.target.parentElement.dataset.key;
        toggleDone(itemKey);
        
    }

    if (e.target.classList.contains('delete')) {
        const itemKey = e.target.parentElement.dataset.key;
        deleteTodo(itemKey);
        counter();
      }

      
    
});


document.addEventListener('DOMContentLoaded', () => {
    const ref = localStorage.getItem('tasksRef');
    if (ref) {
      tasks = JSON.parse(ref);
      tasks.forEach(task => {
        renderTodo(task);
        counter();
      });
    }
  });



  /* FUNCTIONS */

/* create a todo object */
const addTask = (text) => {
    const todoTask = {
        text,
        checked: false,
        id: Date.now(),
    }
    tasks.push(todoTask);
    renderTodo(todoTask);

};


const renderTodo = (todoTask)=> {

    localStorage.setItem('tasksRef', JSON.stringify(tasks));

    
    const item = document.querySelector(`[data-key='${todoTask.id}']`);

    if (todoTask.deleted) {
        // remove the item from the DOM
        item.remove();
        return
      }

    const isChecked = todoTask.checked ? 'done': '';

    const node = document.createElement('li')
    node.setAttribute('class', `todo-item ${isChecked}`);
    node.setAttribute('data-key', todoTask.id);
    node.innerHTML = `
    
    <input class="js-tick" id="${todoTask.id}" type="checkbox" ${isChecked ? "checked" : ""}/>
    <span>${todoTask.text}</span>
    <img class="delete" width="15px" height='15px' src="/images/icon-cross.svg" alt="cross">`
    ;
    todoList.append(node);

    if (item) {
        node.replaceWith(item)
    } else {
        todoList.append(node)
    }
    counter();

}


const toggleDone = (key) => {
    
    const index = tasks.findIndex(task=> task.id === Number(key));

    tasks[index].checked = !tasks[index].checked;
    renderTodo(tasks[index]);
}

const deleteTodo = (key) => {
    const index = tasks.findIndex(item => item.id === Number(key));


    const todoTask = {
        deleted: true,
        ...tasks[index]
      };
      tasks = tasks.filter(item => item.id !== Number(key));
  renderTodo(todoTask);
}


const counter = () => {
    const itemsCounter =  tasks.filter(task=> !task.checked)
    const count = document.getElementById('todosLeft');

    const counterString = itemsCounter.length === 1 ? 'item' : 'items'

 count.innerText = `${itemsCounter.length} ${counterString} left`

}

这里是 HTML:

<body class="light">
  <section class="header">
    
  </section>
  <div class="container">

  <div class="title-theme">
    <h1>Todo</h1>
    <input type="checkbox" id="switch-l" class="themeSwitch">
    <label for="switch-l" id="switch" class="themeSwitch-label"></label>
  </div>
  <div class="todosInput">
    <div id="mark"></div>
    <form class="form" action="" data-new-todo-form>
      <input id="todos" data-new-todo-input type="text" placeholder="Create a new todo..." >
    </form>
  </div>
    <div class="myTodos">
      <ul id="todo-list">
    <--! THE TASKS GOES HERE !-->
      </ul>
    </div>
 <div class="controls">
    <p id="todosLeft">items left</p><!-- Add dynamic number --> 
    <div class="controls-list-div">
      <ul class="controls-list" data-lists>
        <li>All</li> 
        <li>Active</li> 
        <li>Completed</li> 
        </ul>
    </div>
   Clear Completed
   
  </div> 
</div>
  <div class="instruc">
    <p>Drag and drop to reorder list</p>
  </div>   

首先你的 TodoList 需要是不可变的,因为在你点击所有 TodoList 后应该显示所有 Todos。

const renderActiveTodos = () => {
    const ref = localStorage.getItem('tasksRef');
    if (ref) {
      tasks = JSON.parse(ref);
      tasks.filter(item => !item.check).forEach(task => {
        renderTodo(task, true);
        counter();
      });
    }
}

const renderAllTodos = () => {
    const ref = localStorage.getItem('tasksRef');
    if (ref) {
      tasks = JSON.parse(ref);
      tasks.forEach(task => {
        renderTodo(task, true);
        counter();
      });
    }
}

const renderCompletedTodos = () => {
    const ref = localStorage.getItem('tasksRef');
    if (ref) {
      tasks = JSON.parse(ref);
      tasks.filter(item => item.check).forEach(task => {
        renderTodo(task, true);
        counter();
      });
    }
}

但是你应该在你的 renderTodo 函数中添加 preventMutableStorage 来防止本地存储中的数据。然后你可以return返回完整的待办事项列表如果你点击全部

const renderTodo = (todoTask, preventMutableStorage)=> {
    if(!preventMutableStorage){
        localStorage.setItem('tasksRef', JSON.stringify(tasks));
    }
    .....
}

为什么我要更改 renderTodo:

首先假设我们有 todoList = [{id:1, check:false}, {id:2, check:true}, {id:3, check:true}]

当我单击活动时,将调用 renderActiveTodos:

It get data from localstorage
Filter data with check=false => [{id:1, check:false}]
Then we loop through it then call renderTodo
In renderTodo it first set the localstorage again then now the Todo in Localstorage is [{id:1, check:false}]

那么下次我们点击全部:

It can't show [{id:2, check:true}, {id:3, check:true}] cause we already update the todoList in localstorage

这就是我添加 preventMutableStorage 参数以防止本地存储 TodoList 更新的原因

我刚刚在您的代码中发现了一些东西。但所有人都会修复这是工作代码。

https://codepen.io/nguyennghi3489/pen/gOwvNga?editors=1111