在React教程的今天翻译的这一部分中,邀请您继续使用Todo应用程序,并确保单击标志会影响组件的状态。

→
第1部分:课程概述,React,ReactDOM和JSX普及的原因→
第2部分:功能组件→
第3部分:组件文件,项目结构→
第4部分:父级和子级组件→
第5部分:TODO应用程序的开始工作,样式设计的基础→
第6部分:关于本课程的一些功能,JSX和JavaScript→
第7部分:内联样式→
第8部分:继续研究TODO应用程序,熟悉组件的属性→
第9部分:组件属性→
第10部分:使用组件特性和样式的研讨会→
第11部分:动态标记生成和映射数组方法→
第12部分:研讨会,TODO应用程序的第三阶段工作→
第13部分:基于类的组件→
第14部分:关于基于类的组件,组件状态的研讨会→
第15部分:组件健康研讨会→
第16部分:TODO应用程序的第四阶段工作,事件处理→
第17部分:TODO应用程序的第五阶段工作,修改组件的状态→
第18部分:TODO应用程序的第六阶段工作→
第19部分:组件生命周期方法第20部分:条件渲染的第一课→
第21部分:关于条件渲染的第二课和研讨会→
第22部分:TODO应用程序的第七阶段工作,从外部资源下载数据→
第23部分:关于使用表格的第一课→
第24部分:第二形式课→
第25部分:使用表单的研讨会→
第26部分:应用程序体系结构,容器/组件模式→
第27部分:课程项目课33.讲习班。 TODO应用程序。 阶段数6
→
原创▍工作
在本实践课程中,我们将继续使用Todo应用程序,并确保用户操作会影响组件的状态。 它使我们可以将待办事项列表上的项目标记为已完成或未完成。 以下是
App
组件的代码,其中一些可用的工件和注释旨在帮助您完成任务。 实际上,这是今天邀请您执行的操作:
- 在
App
组件中创建一个事件处理程序,以响应标志更改(我们正在谈论onChange
事件)并相应地更改应用程序的状态。 也许这是今天任务中最困难的部分。 为了解决这个问题,请注意代码中的注释和空格。 - 将适当的方法传递给
TodoItem
组件。 - 在
TodoItem
组件中TodoItem
创建一种机制,该机制在onChange
事件onChange
,调用传递给组件实例的方法,并向其传递案例标识符( id
),该标识符对应于用户单击的标志。
这是
App
组件的代码:
import React from "react" import TodoItem from "./TodoItem" import todosData from "./todosData" class App extends React.Component { constructor() { super() this.state = { todos: todosData } this.handleChange = this.handleChange.bind(this) } handleChange(id) {
▍解决方案
首先,创建一个简单的机制来检查对
handleChange()
方法的调用。 即,我们将其转换为以下形式:
handleChange(id) { console.log("Changed", id) }
现在,我们正在根据任务的第2和第3段执行需要执行的操作。 也就是说,我们将在单击该标志与通过将该标志的
id
传递给它的调用
handleChange()
方法之间创建连接。
为了
handleChange()
的引用传递给
TodoItem
组件的实例,我们可以像将属性传递给它一样,并重写用于创建组件列表的代码,如下所示:
const todoItems = this.state.todos.map(item => <TodoItem key={item.id} item={item} handleChange={this.handleChange}/>)
请注意,
TodoItem
组件可以使用的
handleChange
属性包含对
App
组件实例的
handleChange
方法的引用。 在
TodoItem
组件中,可以使用与传递给它的其他属性相同的方式来访问此方法。 在此阶段,
TodoItem
代码如下所示:
import React from "react" function TodoItem(props) { return ( <div className="todo-item"> <input type="checkbox" checked={props.item.completed} onChange={() => console.log("Changed!")} /> <p>{props.item.text}</p> </div> ) } export default TodoItem
要在组件代码中调用
handleChange
方法,可以使用
props.handleChange()
形式的构造。 在这种情况下,此方法需要传递元素的
id
。
onChange
事件
onChange
接受一个事件对象。 我们不需要此对象来调用
handleChange()
方法。 我们重写将
onChange
事件处理程序分配给元素的代码,如下所示:
onChange={(event) => props.handleChange(props.item.id)}
在这里,我们调用
handleChange()
方法,从另一个接受事件对象的函数中,将元素标识符(从传递给它的属性中获取)传递给它。 由于我们不在这里使用此对象,因此可以像下面这样重写代码:
onChange={() => props.handleChange(props.item.id)}
现在尝试运行该应用程序,然后打开控制台,单击复选框。
测试handleChange()方法包含标记标识符的消息,我们通过单击这些标识符进入控制台。 但是这些标志尚未更改外观,因为
handleChange()
方法尚未实现更改组件状态的机制。 结果,我们只处理了任务的第二部分和第三部分,现在我们可以开始处理与国家合作有关的第一部分,这也许是最有趣的部分。
首先,我们需要解决关于数组存储在状态中的状态的问题,该数组的元素响应于单击标志而应进行更改,但我们不应该修改存储在该状态的旧版本中的数组。 也就是说,例如,您不能只是遍历状态中的对象数组,找到必要的元素并更改其
completed
属性。 我们需要在更改状态之后,形成一个新数组,其中一个元素将被更改,其余元素将保持与以前相同。 形成这种数组的方法之一是使用
map()
数组方法,该注释在任务注释中提到。 我们将在
setState()
方法中编写代码。 让我们
handleChange()
App
组件中
handleChange()
方法
handleChange()
代码转换为以下形式:
handleChange(id) { this.setState(prevState => { }) }
现在,使用
map()
方法,我们将遍历
prevState.todos
数组,并在其中查找所需的元素,即将其
id
传递给
handleChange()
方法的
handleChange()
,然后更改其
completed
属性。
map()
方法返回一个新的数组,该数组将在应用程序的新状态中使用,因此我们将该数组写入常量。 看起来是这样的:
handleChange(id) { this.setState(prevState => { const updatedTodos = prevState.todos.map(todo => { if (todo.id === id) { todo.completed = !todo.completed } return todo }) return { todos: updatedTodos } }) }
在此,在使用
map()
处理数组的过程中,如果
handleChange()
id
等于传递给
handleChange()
方法的
id
的元素,则该元素的
completed
属性的值将反转(
true
为
false
,反之亦然)。 之后,无论元素是否已更改,
map()
返回该元素。 它属于同一状态下的新数组(
updatedTodos
数组中由
updatedTodos
常量表示),该索引下相应元素位于该状态的先前版本的
todos
数组中。 在扫描了整个数组并完全形成了
updatedTodos
数组之后,该数组将用作
setState()
方法返回的对象的
todos
属性的值,该方法是该状态的新版本。
如果立即启动该应用程序,则可能会发现这些标志响应了我们的效果。 这表明单击它们会更改应用程序的状态,然后使用新数据重新呈现它们。
总结
今天,我们在编写时使用了一个工作的Todo应用程序,该应用程序使用了许多我们研究过的React概念。 实际上,仍然有可能对其进行改进,尤其是对其进行样式化和扩展其功能。 我们将在以下课程之一中返回他。
亲爱的读者们! 您应付今天的实际工作了吗?
