| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- import { useState, useRef } from 'react'
- import './App.css'
- interface Todo {
- id: number,
- text: string,
- completed: boolean
- }
- type Filter = 'all' | 'active' | 'completed';
- function filterTodos(todos: Todo[], filter: Filter): Todo[] {
- switch (filter) {
- case 'all':
- return todos;
- case 'active':
- return todos.filter(todo => !todo.completed);
- case 'completed':
- return todos.filter(todo => todo.completed);
- default:
- return todos;
- }
- }
- function Header({ addTodo }: { addTodo: (text: string) => void }) {
- const inpRef = useRef<HTMLInputElement>(null);
- const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
- if (e.keyCode === 13) {
- addTodo(inpRef.current!.value);
- inpRef.current!.value = ""
- }
- }
- return (
- <div>
- <header className="header">
- <h1>todos</h1>
- <input
- ref={inpRef}
- autoFocus
- autoComplete="off"
- placeholder="输入您要完成的任务?"
- className="new-todo"
- onKeyDown={handleKeyDown}
- />
- </header>
- </div>
- )
- }
- function Main({ onToggleAll, allCompleted }: { onToggleAll: (val: boolean) => void, allCompleted: boolean }) {
- const handleToggle = () => {
- allCompleted = !allCompleted;
- onToggleAll(allCompleted)
- }
- return (
- <div>
- <input id="toggle-all" type="checkbox" className="toggle-all" onChange={handleToggle} checked={allCompleted} />
- <label htmlFor="toggle-all"></label>
- </div>
- )
- }
- function TodoItem({ todo, onDelete, onActive }: { todo: Todo, onDelete: (id: number) => void, onActive: (id: number) => void }) {
- const deleteTodo = (val: number) => {
- onDelete(val)
- }
- const activeTodo = (val: number) => {
- onActive(val)
- }
- return (
- <li className={todo.completed ? 'completed' : ''}>
- <div className="view">
- <input type="checkbox" className="toggle" checked={todo.completed} onChange={() => activeTodo(todo.id)} />
- <label>{todo.text}</label>
- <button className="destroy" onClick={() => deleteTodo(todo.id)}></button>
- </div>
- <input type="text" className="edit" />
- </li>
- )
- }
- function Footer({ count, clearAll, filter, tabFilter }: { count: number, clearAll: () => void, filter: Filter, tabFilter: (val: string) => void }) {
- console.log(filter, 'filter')
- return (
- <div>
- <span className="todo-count"><strong>{count}</strong> items left </span>
- <ul className="filters">
- <li><a href="#/all" onClick={() => tabFilter('all')} className={filter == 'all' ? 'selected' : ''}>All</a></li>
- <li><a href="#/active" onClick={() => tabFilter('active')} className={filter === 'active' ? 'selected' : ''}>Active</a></li>
- <li><a href="#/completed" onClick={() => tabFilter('completed')} className={filter === 'completed' ? 'selected' : ''}>Completed</a></li>
- </ul>
- <button className="clear-completed" onClick={clearAll}>Clear completed</button>
- </div>
- )
- }
- function App() {
- const [todos, setTodos] = useState<Todo[]>([
- {
- id: 1, text: '吃饭', completed: false
- },
- {
- id: 2, text: '睡觉', completed: false
- },
- {
- id: 3, text: '打豆豆', completed: true
- }
- ])
- const completeCount = todos.filter((item) => !item.completed).length;
- const isCompleted = todos.every((item) => item.completed);
- const [isFilter, setIsFilter] = useState<Filter>('all');
- const newArr = filterTodos(todos, isFilter);
- const handleAdd = (val: string) => {
- setTodos([...todos, {
- id: Date.now(),
- text: val,
- completed: false
- }])
- }
- const handleDelete = (val: number) => {
- setTodos((prevTodos) => { return prevTodos.filter((todo) => todo.id !== val) })
- }
- const handleAvtive = (val: number) => {
- setTodos((prevTodos) => prevTodos.map((todo) => {
- return todo.id === val ? { ...todo, completed: !todo.completed } : todo
- }))
- }
- const handleAll = (val: boolean) => {
- setTodos((prev) => prev.map((todo) => {
- return { ...todo, completed: val }
- }))
- }
- const handleClear = () => {
- setTodos([...todos.filter((todo) => !todo.completed)])
- }
- const handleSet = (val: Filter) => {
- setIsFilter(val)
- }
- return (
- <>
- <div id="app">
- <section className="todoapp">
- <Header addTodo={handleAdd}></Header>
- <section className="main">
- <Main onToggleAll={handleAll} allCompleted={isCompleted}></Main>
- <ul className="todo-list">
- {
- newArr.map((todo) => {
- return (
- <TodoItem key={todo.id} todo={todo} onDelete={handleDelete} onActive={handleAvtive}></TodoItem>
- )
- })
- }
- </ul>
- </section>
- <footer className="footer">
- <Footer count={completeCount} clearAll={handleClear} filter={isFilter} tabFilter={handleSet}></Footer>
- </footer>
- </section>
- </div>
- </>
- )
- }
- export default App
|