我是靠谱客的博主 健康绿茶,这篇文章主要介绍React 入门实例 学习笔记 四、 TodoApp 功能分步实现,现在分享给大家,希望可以做个参考。

博主介绍:大爽歌, b站小UP主 ,直播编程+红警三 ,python1对1辅导老师 。

本博客为microsoft的的Frontend Bootcamp 的day1中 react 部分的学习笔记

笔记目录: React 入门实例 学习笔记 目录
请先看目录,按照目录先后顺序阅读实践
本博客有对应视频版本,具体见目录。

0 分支检出

使用vs-code
从上一节的分支todoapp-v1,检出分支todoapp-v2
具体见视频:
【代码过程】 React 入门实例 TodoApp 学习梳理笔记

1 TodoList 实现

之前TodoList的TodoListItem 中的内容是写死的。
这里改为根据Todos的数据,动态生成内容。

再修改src/TodoApp.tsx,添加defaultTodos
TodoApp中添加todos并进行传参。
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import React from 'react'; import { TodoHeader } from './components/TodoHeader.tsx'; import { TodoList } from './components/TodoList.tsx'; import { TodoFooter } from './components/TodoFooter.tsx'; const defaultTodos = [ { id: '01', label: 'Todo 1', status: 'completed', }, { id: '02', label: 'Todo 2', status: 'active', }, { id: '03', label: 'Todo 2', status: 'active', }, { id: '04', label: 'Todo 3', status: 'completed', }, ] export const TodoApp = props => { const [todos, setTodos] = React.useState(defaultTodos); return ( <div> <TodoHeader /> <TodoList todos={todos}/> <TodoFooter /> </div> ) }

再修改src/components/TodoList.tsx成如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react'; import { TodoListItem } from './TodoListItem.tsx'; export const TodoList = (props) => { const { todos } = props; return ( <ul className='todos'> {todos.map((todo)=> <TodoListItem key={todo.id} {...todo} />)} </ul> ) }

再修改src/components/TodoListItem.tsx成如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react'; export const TodoListItem = (props) => { const { label, status, id } = props; return ( <li className="todo"> <label> <input type="checkbox" checked={status === 'completed'} /> {label} </label> </li> ); }

然后TodoList部分就可以动态展示todos的数据内容了

2 TodoListItem checkbox(复选框) 功能实现

目前TodoListItem的 checkbox(复选框) 是无法勾选的。
需要实现选中和取消选中功能。

修改src/TodoApp.tsx, 添加toggleCompleted方法并传参给TodoList
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React from 'react'; import { TodoHeader } from './components/TodoHeader.tsx'; import { TodoList } from './components/TodoList.tsx'; import { TodoFooter } from './components/TodoFooter.tsx'; const defaultTodos = [ { id: '01', label: 'Todo 1', status: 'completed', }, { id: '02', label: 'Todo 2', status: 'active', }, { id: '03', label: 'Todo 2', status: 'active', }, { id: '04', label: 'Todo 3', status: 'completed', }, ] export const TodoApp = props => { const [todos, setTodos] = React.useState(defaultTodos); const toggleCompleted = (id) => { const newTodos = todos.map((todo)=>{ if (todo.id === id){ return {...todo, status: todo.status === 'active' ? 'completed' : 'active'}; } else { return todo; } }); setTodos(newTodos); } return ( <div> <TodoHeader /> <TodoList todos={todos} toggleCompleted={toggleCompleted} /> <TodoFooter /> </div> ) }

修改src/components/TodoList.tsx, 接受toggleCompleted方法并传参给TodoListItem
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react'; import { TodoListItem } from './TodoListItem.tsx'; export const TodoList = (props) => { const { todos, toggleCompleted } = props; return ( <ul className='todos'> {todos.map((todo)=> <TodoListItem key={todo.id} {...todo} toggleCompleted={toggleCompleted} />)} </ul> ) }

修改src/components/TodoListItem.tsx, 接受toggleCompleted方法并使用。
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from 'react'; export const TodoListItem = (props) => { const { label, status, id, toggleCompleted } = props; const handleCheck = () => { toggleCompleted(id); } return ( <li className="todo"> <label> <input type="checkbox" checked={status === 'completed'} onChange={handleCheck}/> {label} </label> </li> ); }

这样TodoListItem的 checkbox(复选框) 的勾选功能就实现好了。

3 TodoHeader 实现

修改src/TodoApp.tsx, 添加filter 属性和 addTodo 方法,并传参给需要的组件。

修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import React from 'react'; import { TodoHeader } from './components/TodoHeader.tsx'; import { TodoList } from './components/TodoList.tsx'; import { TodoFooter } from './components/TodoFooter.tsx'; const defaultTodos = [ { id: '01', label: 'Todo 1', status: 'completed', }, { id: '02', label: 'Todo 2', status: 'active', }, { id: '03', label: 'Todo 2', status: 'active', }, { id: '04', label: 'Todo 3', status: 'completed', }, ] export const TodoApp = props => { const [filter, setFilter] = React.useState('all'); const [todos, setTodos] = React.useState(defaultTodos); const addTodo = (label) => { const getId = () => Date.now().toString(); const newTodo = { id: getId(), label: label, status: 'active', }; setTodos([...todos, newTodo]); } const toggleCompleted = (id) => { const newTodos = todos.map((todo)=>{ if (todo.id === id){ return {...todo, status: todo.status === 'active' ? 'completed' : 'active'}; } else { return todo; } }); setTodos(newTodos); } return ( <div> <TodoHeader filter={filter} setFilter={setFilter} addTodo={addTodo} /> <TodoList todos={todos} filter={filter} toggleCompleted={toggleCompleted} /> <TodoFooter /> </div> ) }

修改src/components/TodoHeader.tsx
添加各种事件处理方法
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React from 'react'; export const TodoHeader = (props) => { const [inputText, setInputText] = React.useState(''); const { filter, setFilter, addTodo } = props; const onInput = (e) => { setInputText(e.target.value); } const onSubmit = () => { if (inputText.length > 0) { addTodo(inputText); }; setInputText(''); } const onFilter = (e) => { setFilter(e.currentTarget.textContent); } return ( <header> <h1>todos <small>(Basic implementation)</small></h1> <div className="addTodo"> <input className="textfield" placeholder = "add todo" value={inputText} onChange={onInput} /> <button className="submit" onClick={onSubmit}>Add</button> </div> <nav className="filter"> <button className={filter === 'all' ? 'selected' : ''} onClick={onFilter}>all</button> <button className={filter === 'active' ? 'selected' : ''} onClick={onFilter}>active</button> <button className={filter === 'completed' ? 'selected' : ''} onClick={onFilter}>completed</button> </nav> </header> ) }

修改src/components/TodoList.tsx
接受filter参数,并处理todos数据得到filteredTodos

修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React from 'react'; import { TodoListItem } from './TodoListItem.tsx'; export const TodoList = (props) => { const { todos, filter, toggleCompleted } = props; const filteredTodos = todos.filter((todo) => { if (todo.status === 'cleared'){ return false; }; if (filter === 'all') { return true; } else if (filter === 'completed') { return todo.status === 'completed'; } else if (filter === 'active'){ return todo.status === 'active'; }; return false; }) return ( <ul className='todos'> {filteredTodos.map((todo)=> <TodoListItem key={todo.id} {...todo} toggleCompleted={toggleCompleted} />)} </ul> ) }

到这里,顶部栏的添加新todo,和过滤功能(点击all, active, completed切换)就实现好了。

4 TodoFooter 实现

最后还要实现,条目数量统计,和清理completed数据的按钮。

修改src/TodoApp.tsx, 添加clearCompleted方法并传参给TodoFooter,
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import React from 'react'; import { TodoHeader } from './components/TodoHeader.tsx'; import { TodoList } from './components/TodoList.tsx'; import { TodoFooter } from './components/TodoFooter.tsx'; const defaultTodos = [ { id: '01', label: 'Todo 1', status: 'completed', }, { id: '02', label: 'Todo 2', status: 'active', }, { id: '03', label: 'Todo 2', status: 'active', }, { id: '04', label: 'Todo 3', status: 'completed', }, ] export const TodoApp = props => { const [filter, setFilter] = React.useState('all'); const [todos, setTodos] = React.useState(defaultTodos); const addTodo = (label) => { const getId = () => Date.now().toString(); const newTodo = { id: getId(), label: label, status: 'active', }; setTodos([...todos, newTodo]); } const toggleCompleted = (id) => { const newTodos = todos.map((todo)=>{ if (todo.id === id){ return {...todo, status: todo.status === 'active' ? 'completed' : 'active'}; } else { return todo; } }); setTodos(newTodos); } const clearCompleted = () => { const updateTodos = todos.map((todo) => { if(todo.status === 'completed') { return {...todo, status: 'cleared'}; } else { return todo; } }); setTodos(updateTodos); } return ( <div> <TodoHeader filter={filter} setFilter={setFilter} addTodo={addTodo} /> <TodoList todos={todos} filter={filter} toggleCompleted={toggleCompleted} /> <TodoFooter todos={todos} clearCompleted={clearCompleted} /> </div> ) }

修改src/components/TodoFooter.tsx,接受属性,并使用。
修改后如下

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react'; export const TodoFooter = (props) => { const { clearCompleted, todos } = props; const itemCount = todos.filter((todo) => todo.status === 'active' ).length; return ( <footer> <span>{itemCount} item{itemCount === 1 ? '' : 's'} left</span> <button className="submit" onClick={clearCompleted} >Clear Completed</button> </footer> ) }

到这里,整个TodoApp的功能就基本实现完成了。

实现后的效果见视频16:35处

最后

以上就是健康绿茶最近收集整理的关于React 入门实例 学习笔记 四、 TodoApp 功能分步实现的全部内容,更多相关React内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部