思路
1. 确定功能需求
-
首先明确要实现一个简单的任务管理功能,具体包括:
- 能够添加新任务。
- 可以标记任务为已完成状态(并在界面上有相应显示)。
- 能够删除不再需要的任务。
2. 选择技术框架及相关工具
- 基于 React 框架来开发,因为 React 提供了方便的组件化开发模式以及状态管理机制,适合构建这样的交互式 UI 应用。
- 选用
useState
钩子函数来处理组件内的状态管理,它能让函数组件轻松拥有类似类组件中state
的功能。
3. 状态设计
-
考虑到需要管理任务列表以及当前正在输入的新任务内容,确定了以下两个状态变量:
tasks
:用于存储所有任务的数组,每个任务对象包含任务的文本内容(text
)和完成状态(completed
)两个属性。初始化为空数组,因为一开始没有任务。task
:用来保存用户在输入框中输入的新任务文本,初始化为空字符串。
4. 输入框及添加任务功能实现
-
创建一个文本输入框
<input>
:- 通过
value={task}
和onChange={onChange}
实现输入框与task
状态的双向绑定,确保输入框能实时反映task
状态的变化,并且用户输入能更新task
状态。
- 通过
-
编写
addTask
函数来实现添加任务功能:- 先检查
task
状态的值是否为空字符串(经过trim
去除前后空格),只有非空时才进行添加操作,保证添加有意义的任务。 - 通过
setTasks([...tasks, { text: task, completed: false }])
利用数组展开运算符复制原tasks
数组并添加新任务对象到末尾,新任务对象的text
取自当前task
状态,completed
初始设为false
。 - 最后将
task
状态重置为空字符串,方便用户输入下一个任务。
- 先检查
5. 完成任务状态切换功能实现
-
设计
finishTask
函数来处理任务完成状态的切换:- 函数接收任务在
tasks
数组中的索引作为参数。 - 先通过
const newTasks = [...tasks];
复制一份当前的tasks
数组到newTasks
。 - 然后根据传入的索引找到对应任务对象并将其
completed
属性取反,实现状态切换。 - 最后通过
setTasks(newTasks)
更新tasks
状态,使组件重新渲染以展示任务完成状态的变化。
- 函数接收任务在
6. 删除任务功能实现
-
编写
deleteTask
函数用于删除任务:- 同样接收任务在
tasks
数组中的索引作为参数。 - 利用
setTasks(tasks.filter((_, i) => i!== index))
通过filter
函数对原tasks
数组进行过滤,保留索引不等于传入参数index
的任务,从而实现删除指定索引任务的目的。
- 同样接收任务在
7. 界面渲染
-
在组件的返回值部分,按照以下逻辑构建 UI 界面:
-
先放置输入框和添加任务的按钮,方便用户输入新任务并添加。
-
接着通过
tasks.map
遍历tasks
数组,为每个任务创建一个列表项<li>
:- 为列表项设置唯一的
key
属性,便于 React 正确识别和更新列表项。 - 根据任务的完成状态设置列表项的文本装饰样式(完成则添加删除线)。
- 在列表项内显示任务文本,并放置切换完成状态和删除任务的按钮,分别绑定对应的
finishTask
和deleteTask
函数及相应索引
- 为列表项设置唯一的
-
实现过程
1. 组件定义及状态初始化
jsx
export default function App() {
const [tasks, setTasks] = useState([]);
const [task, setTask] = useState('');
//... 其他代码
}
-
定义了一个名为
App
的函数组件,这是 React 应用中常见的组件定义方式。 -
使用
useState
初始化了两个状态变量:tasks
:它是一个数组,用于存储所有的任务对象。初始值被设置为空数组[]
,表示一开始没有任何任务。task
:它是一个字符串类型的状态变量,用于存储用户在输入框中输入的新任务内容。初始值为空字符串''
。
2. 处理输入框值变化的函数
jsx
const onChange = e => setTask(e.target.value);
这是一个处理输入框 onChange
事件的函数。当用户在输入框中输入内容时,该函数会被触发。它通过 setTask
函数将输入框的当前值更新到 task
状态变量中,从而实现了输入框内容与 task
状态的双向绑定。
3. 添加任务的函数
jsx
const addTask = () => {
if (task.trim()) {
setTasks([...tasks, { text: task, completed: false }]);
setTask('');
}
};
-
addTask
函数用于将新任务添加到tasks
列表中。 -
首先,通过
task.trim()
检查用户输入的任务内容是否为空字符串(去除前后空格后)。如果不为空:- 使用
setTasks
函数来更新tasks
状态。它通过展开运算符...
将原有的tasks
数组内容复制一份,并添加一个新的任务对象到数组末尾。新任务对象包含两个属性:text
属性的值取自当前task
状态变量的值,completed
属性初始值被设置为false
,表示任务尚未完成。 - 最后,将
task
状态变量重置为空字符串''
,以便用户可以输入下一个新任务。
- 使用
4. 完成任务切换状态的函数
jsx
const finishTask = (index) => {
const newTasks = [...tasks];
newTasks[index].completed =!newTasks[index].completed;
setTasks(newTasks);
};
finishTask
函数用于切换指定任务的完成状态。- 函数接收一个参数
index
,表示要切换完成状态的任务在tasks
数组中的索引位置。 - 首先,通过展开运算符复制一份当前的
tasks
数组到newTasks
变量中。 - 然后,根据传入的索引
index
,找到对应的任务对象,并将其completed
属性的值取反,从而实现任务完成状态的切换。 - 最后,使用
setTasks
函数将更新后的newTasks
数组设置为新的tasks
状态,这会导致组件重新渲染,以反映任务完成状态的变化。
5. 删除任务的函数
jsx
const deleteTask = index => setTasks(tasks.filter((_, i) => i!== index));
deleteTask
函数用于从tasks
数组中删除指定索引的任务。- 函数接收一个参数
index
,表示要删除的任务在tasks
数组中的索引位置。 - 通过
tasks.filter((_, i) => i!== index)
对原有的tasks
数组进行过滤操作。filter
方法会遍历数组中的每个元素,对于索引不等于传入的index
的元素,会被保留在新的数组中,从而实现了删除指定索引任务的目的。 - 最后,使用
setTasks
函数将过滤后的新数组设置为新的tasks
状态,使得组件重新渲染时不再显示已删除的任务。
6. 组件的渲染部分
jsx
return (
<div>
<input
type="text"
value={task}
onChange={onChange}
placeholder="Add a new task..."
/>
<button onClick={addTask}>Add</button>
<ul>
{tasks.map((item, index) => (
<li key={index} style={{ textDecoration: item.completed? 'line-through' : 'none' }}>
{item.text}
<button onClick={() => finishTask(index)}>Toggle</button>
<button onClick={() => deleteTask(index)}>Delete</button>
</li>
))}
</ul>
</div>
);
-
在组件的
return
语句中,定义了组件的 UI 结构。 -
首先,有一个输入框
<input>
:type="text"
表示这是一个文本输入框。value={task}
将输入框的值与task
状态变量进行绑定,确保输入框显示的内容始终与task
状态一致。onChange={onChange}
绑定了输入框的onChange
事件处理函数,当输入框内容改变时,会触发onChange
函数来更新task
状态。placeholder="Add a new task..."
设置了输入框的占位符文本,提示用户输入新任务。
-
接着,有一个按钮
<button>
:onClick={addTask}
绑定了点击事件处理函数,当用户点击该按钮时,会触发addTask
函数来添加新任务到tasks
列表中。
-
然后,通过
tasks.map
方法遍历tasks
数组中的每个任务对象:-
对于每个任务对象,创建一个
<li>
列表项元素。 -
key={index}
为每个列表项设置了一个唯一的key
属性,这是 React 在渲染列表时要求的,用于提高渲染性能和正确识别列表项的更新。 -
根据任务对象的
completed
属性值来设置列表项的文本装饰样式。如果completed
为true
,则textDecoration
设置为line-through
,表示任务已完成并添加删除线效果;如果为false
,则设置为none
,表示任务未完成。 -
在列表项内部,显示任务的文本内容
{item.text}
。 -
还有两个按钮:
- 一个按钮的
onClick
绑定了finishTask
函数,并传入当前任务的索引index
,用于切换任务的完成状态。 - 另一个按钮的
onClick
绑定了deleteTask
希望对你有所帮助。函数,并传入当前任务的索引index
,用于删除当前任务。
- 一个按钮的
-
7. 实现截图
