功能说明
通过react实现一个简易版的todolist案例 功能如下
- 添加待办事项
- 删除待办事项
- 反转待办事项状态
- 统计分类 (即筛选 已办 未办 全部
步骤实现
- 创建项目
npx create-next-app@latest
简单配置一下 使用typescript
目录结构如下
- 代码
新建组件
四个组件搭建好基本结构如下
//TodoList
function TodoList () {
return (
<div>
<h1>AddTodo</h1>
</div>
);
}
export default TodoList;
//TodoItem
function TodoItem (prop: any) {
return (
<div>
{prop.todo.title}
</div>
);
}
export default TodoItem;
//TodoFilter
function TodoFilter() {
return (
<div>
<button>All</button>
<button>Active</button>
<button>Completed</button>
</div>
);
}
export default TodoFilter;
//AddTodo
function AddTodo () {
return (
<div>
<h1>AddTodo</h1>
</div>
);
}
export default AddTodo;
页面组件中引入这四个初始化好的数组
import AddTodo from "./components/AddTodo";
import TodoList from "./components/TodoList";
import TodoFilter from "./components/TodoFilter";
import { useState } from "react";
export default function Home() {
return (
<div>
<h1>TodoList</h1>
<AddTodo />
<TodoList />
<TodoFilter />
</div>
);
}
定义待办的数据属性 每个待办应该有内容 id 以及是否完成的状态
在src下新建type.ts并导出
export interface Todo {
id: number;
text: string;
completed: boolean;
}
引入Todo类型并使用对应的状态
添加功能及对应实现
const addTodo = (text: string) => {
const newTodo = {
id: Date.now(),
text,
completed: false,
};
setTodos([...todos, newTodo]);
}
删除功能及对应实现
const deleteTodo = (id: number) => {
setTodos(todos.filter(todo => todo.id !== id));
}
切换功能及对应实现
const toggleTodo = (id: number) => {
setTodos(todos.map(todo => {
if (todo.id === id) {
return {
...todo,
completed: !todo.completed,
};
}
return todo;
}));
}
筛选功能
要添加一个标记状态
const [filter, setFilter] = useState<string>('all');
filter方法
const getFilteredTodos = () => {
switch (filter) {
case 'completed':
return todos.filter(todo => todo.completed);
case 'active':
return todos.filter(todo => !todo.completed);
default:
return todos;
}
}
实现位置
完整的添加功能代码
import React, { useState } from 'react';
interface addTodoProps {
addTodo: (text: string) => void;
}
function AddTodo ({addTodo} : addTodoProps) {
const [text, setText] = useState<string>('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!text.trim()) return;
addTodo(text);
setText('');
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button>Add</button>
</form>
);
}
export default AddTodo;
Todolist完整代码 主要有todo 删除和反转 接受从page传过来的props 定义一个interface来接收
import { Todo } from "../type";
import TodoItem from "./TodoItem";
interface TodoListProps {
todos: Array<Todo>;
deleteTodo: (id: string) => void;
toggleTodo: (id: string) => void;
}
function TodoList ({todos, deleteTodo, toggleTodo} : TodoListProps) {
return (
<ul>
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} deleteTodo={deleteTodo} toggleTodo={toggleTodo} />
))}
</ul>
);
}
export default TodoList;
接收完成后再传入TodoItem组件里
TodoItem的完整代码
接收props, 定义点击的实现函数
import {Todo} from '../type';
interface TodoItemProps {
todo: Todo;
deleteTodo: (id: string) => void;
toggleTodo: (id: string) => void;
}
function TodoItem ({todo, deleteTodo, toggleTodo} : TodoItemProps) {
return (
<li style={{textDecoration: todo.completed ? 'line-through' : 'none'}}>
{todo.text}
<button onClick={() => toggleTodo(todo.id)}>Toggle</button>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
);
}
export default TodoItem;
现在只差TodoFilter啦
筛选只需要改变filter的值 filter的值一改变 对应的返回给todolist的todos数组就会改变 从而页面就会改变
interface TodoFilterProps {
setFilter: (filter: string) => void;
}
function TodoFilter({setFilter} : TodoFilterProps) {
return (
<div>
<button onClick={() => setFilter('all')}>All</button>
<button onClick={() => setFilter('completed')}>Completed</button>
<button onClick={() => setFilter('active')}>Active</button>
</div>
);
}
export default TodoFilter;
总结
总体来说自己react+ts这么来写很熟练, 实现的功能非常简单没有写样式,朴实无华版,中间有一些报错主要是ts类型的错误,用ts一方面会有这种类型错误,一方面因为类型提示很好找这个错误.总而言之写这个小demo还是有所收获的