我们使用带有打字稿的普通 vite 项目来理解打字稿,并使用本地存储来存储待办事项。
<meta charset="utf-8"><link rel="icon" type="image/svg+xml" href="/vite.svg"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>vite + ts</title><link rel="stylesheet" href="./src/style.css"><div id="app"> <div class="container"> <h1>my todo list</h1> <form id="myform"> <input required type="text" id="inputtodo" placeholder="enter todo"><button type="submit" id="btnsubmit">add</button> </form> <div class="todos-container"> <!-- <div class="todo-item"> <input id="iscomplete" type="checkbox"> <p id="todotext">my today todo</p> <button id="btndelete">x</button> </div> --> </div> </div> </div> <script type="module" src="/src/main.ts"></script>
.container{ max-width: 700px; margin-inline: auto; display: flex; align-items: center; justify-content: center; flex-direction: column; } form #inputtodo{ padding: 8px 15px; } form #btnsubmit{ padding: 8px 15px; } .todos-container{ padding: 10px; width: 100%; width: fit-content; } .todo-item{ padding: 5px; border: 1px solid gray; gap: 20px; width: 100%; display: flex; align-items: center; } .textcut{ text-decoration: line-through; }
interface Todo{ content: string, isComplete: boolean, readonly id:string } let todos:Todo[] = []; const todosContainer = document.querySelector('.todos-container')!; function genrateTodo(id: string, content:string, isComplete:boolean){ const itemContainer:HTMLDivElement = document.createElement('div'); itemContainer.classList.add('todo-item'); // checkbox const checkbox: HTMLInputElement = document.createElement('input'); checkbox.type = "checkbox"; checkbox.checked = isComplete checkbox.onchange = () => { todos.find(todo => { if(todo.id === id) todo.isComplete = checkbox.checked; // save updated todo localStorage.setItem('todos', JSON.stringify(todos)); }) todoText.className = checkbox.checked ? 'textCut' : ''; } // paragraph content const todoText:HTMLParagraphElement = document.createElement('p'); todoText.innerHTML = content; todoText.className = isComplete ? 'textCut' : ''; // delete button const btnDelete: HTMLButtonElement = document.createElement('button'); btnDelete.textContent = 'X'; btnDelete.onclick = () => { todos = todos.filter(todo => todo.id !== id); localStorage.setItem('todos', JSON.stringify(todos)); renderTodos(todos); } itemContainer.append(checkbox, todoText, btnDelete); todosContainer.appendChild(itemContainer); } // add todo const form = document.getElementById('myForm')!; form.onsubmit = (e: SubmitEvent) => { e.preventDefault(); const inputElement = document.getElementById('inputTodo') as HTMLInputElement; let value:string = inputElement.value; const newTodo:Todo = { id: String(Math.random() * 1000), content: value, isComplete: false } todos.push(newTodo); inputElement.value = ""; localStorage.setItem('todos', JSON.stringify(todos)); renderTodos(todos); } function renderTodos(todos: Todo[]){ todosContainer.innerHTML = ""; todos.forEach(todo => { genrateTodo(todo.id, todo.content, todo.isComplete); }) } const jsonTodos = localStorage.getItem('todos')!; const storedTodos : Todo[] = JSON.parse(jsonTodos); todos = storedTodos; renderTodos(todos);