在React培训课程的今天翻译中,邀请您完成表单任务。

→
第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部分:课程项目课43.讲习班。 处理表格
→
原创▍工作
在本实践课程中,邀请您提出
App
组件的代码,该代码位于create-react-app创建的标准项目的
App.js
文件中。 这是代码:
import React, {Component} from "react" class App extends Component { constructor() { super() this.state = {} } render() { return ( <main> <form> <input placeholder="First Name" /><br /> <input placeholder="Last Name" /><br /> <input placeholder="Age" /><br /> {/* */} <br /> {/* */} <br /> {/* */} <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {/* */}</p> <p>Your age: {/* */}</p> <p>Your gender: {/* */}</p> <p>Your destination: {/* */}</p> <p> Your dietary restrictions: {/* */} </p> </main> ) } } export default App
通常,您的任务是确保用户在使用表单控件时输入的数据立即显示在此表单下方的文本中。 完成任务时,请利用
托管组件技术。 应该注意的是,提供给您的任务是
此任务的改编版,因此您可以对其进行研究,以更好地了解邀请您创建和配置的控件的功能。
这是组件现在在屏幕上显示的内容。
浏览器中的应用▍解决方案
您可以从不同角度解决向您提出的问题的解决方案。 我们将从将所需的所有内容置于状态开始,然后设置组件的控件和其他机制。
此刻,组件的状态如下图所示。
this.state = { firstName: "", lastName: "", age: 0, gender: "", destination: "", dietaryRestrictions: [] }
有必要考虑以下事实:在处理程序的过程中,可能会发现,例如,更方便地进行不同的状态初始化。 如果遇到类似情况,将更改状态初始化代码。 尤其是,现在可能会由于
age
属性中写入的数字0(可能存储用户输入的年龄)而引起一些疑问。 也许有必要对标志数据存储系统进行其他操作,该系统现在由
dietaryRestrictions
属性表示,并由一个空数组初始化。
现在,在状态初始化之后,让我们来设置控件。 由于代码已经对输入字段进行了描述-让我们开始使用它们。
这些控件将需要通过设置其
name
属性来命名,以使其与状态属性的名称相匹配,状态属性的名称将存储在这些字段中输入的数据。 它们应具有
value
属性,其值是根据状态中存储的数据确定的。 在每个字段中输入数据时,需要将输入的数据传递给组件,这导致它们需要具有
onChange
事件
onChange
。 所有这些考虑因素导致以下事实:现在对字段的描述如下所示:
<input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" />
作为用于处理这些字段的
onChange
事件的方法,
this.handleChange
仍然不存在。 创建此方法:
handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) }
在这里,我们从
event.target
对象中提取
name
和
value
属性,然后使用它们来设置相应的状态属性。 目前,这样的通用事件处理程序代码将适合我们,但是稍后,当我们开始使用标志时,我们将对其进行更改。
不要忘记在组件构造函数中执行的
this
绑定:
this.handleChange = this.handleChange.bind(this)
为了在
firstName
,
secondName
和
age
字段中输入的数据页面的底部实现输出,
secondName
将使用相应的
<p>
元素,使其具有以下格式:
<p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p>
现在,让我们看看我们得到了什么。
浏览器中的应用如您所见,在用于输入年龄的字段中,未显示任何提示。 而是显示
age
的state属性中设置的值,即0。我们需要在空字段中提示。 让我们尝试用
null
代替state的
age
null
。 之后,事实证明该表单看起来应该是正确的,但是控制台中关于
age
字段显示以下警告:
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components
结果,我们将需要用一个空字符串替换
age
state属性的值,将状态初始化代码转换为以下形式:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", dietaryRestrictions: [] }
现在尝试表格。 打开后,其外观将与工作开始时的外观相同,即提示将返回到“
age
字段。 填写字段时,输入的数据将显示在页面底部。
浏览器中的应用如您所见,在工作的这个阶段,所有功能都按预期运行。
现在,我们将从事新的元素。 处理表单的下一步将是向其添加开关。
我们将开关包装在
<label>
,这不仅使我们可以对开关进行签名,而且还可以确保单击此签名(即在其父元素上)导致对其进行选择。
使用开关时,要记住它们是带有
checked
属性的标志和具有
value
属性的文本字段的组合。 这些开关组成一个组,其中为每个开关分配相同的名称,并根据配置的条件设置开关的
checked
属性,这样就不可能打开多个开关(属于同一组)。
onChange
为
onChange
开关的事件处理程序。
结果,开关描述代码将如下所示:
<label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label>
现在,我们将处理位于页面底部的相应
<p>
元素,如下所示:
<p>Your gender: {this.state.gender}</p>
之后,可以测试表格。 启动后立即取消选择两个开关,因为状态存储在一个值中,该值不允许在将其
checked
属性设置为
true
时执行任何检查。 单击其中之一后,相应的值进入状态(存储在开关的
value
属性中),选中该开关,相应的文本显示在表单底部。
浏览器中的应用现在让我们在组合框上工作。 他的工件如下所示:
<select> <option></option> <option></option> <option></option> <option></option> </select>
此代码表明我们计划描述一个包含四个项目的组合框。
<select>
标记及其
<option>
标记具有
value
属性。 但是,这些属性具有不同的含义。 分配给
<option>
元素的值表示在选择此元素时相应的状态属性。 这些是应该在下拉列表中的行。 在我们的情况下,这些是某些目的地,例如国家/地区。 让我们用小写字母写出它们的名称,以便它们的外观与代码中其他元素的
value
属性的值相对应。 之后,组合框的代码将如下所示:
<select value=> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
如果我们谈论
<select>
的
value
属性,那么这里不会显示一些硬编码的值,而是指向相应的state属性的链接:
<select value={this.state.destination}> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
为该字段分配其他属性。 特别是,与状态中的属性名称相对应的名称,以及
onChange
事件
onChange
this.handleChange
。
<select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
现在,我们将配置
<p>
元素的描述,该描述将显示在
destination
字段中选择的内容:
<p>Your destination: {this.state.destination}</p>
如果您现在在浏览器中查看页面,您会看到在字段中自动选择了列表的第一个元素,但这显然不会导致状态更新,因为在
Your destination:
行中的冒号后面没有显示任何内容。
浏览器中的应用为了使
germany
价值落入该状态,您需要打开组合框并首先选择其他内容,然后选择
Germany
。
通常,为了考虑列表字段的此功能,在它们的列表中,作为第一个元素,他们放置了诸如带有空值的元素以及带有诸如
-- Please Choose a destination --
类的文本的东西。 在我们的情况下,可能看起来像这样:
<select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select>
我们将专注于设置组合框的此选项。
现在,也许让我们处理与标志相关的任务中最困难的部分。 在这里值得
dietaryRestrictions
的是,计划用于标志的状态属性
dietaryRestrictions
是用空数组初始化的。 现在,在使用控件时,感觉最好将此字段表示为对象。 因此,使用以友好名称的该对象的属性形式而不是数组元素的形式表示单个标志的实体将更加方便。 对象的属性(现在将由
dietaryRestrictions
状态
dietaryRestrictions
)将包含布尔值,该布尔值指示是否清除了对应的复选框(
false
)或选中了(
true
)。 现在状态初始化代码将如下所示:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", dietaryRestrictions: { isVegan: false, isKosher: false, isLactoseFree: false } }
如您所见,我们计划创建三个标志。 加载页面后,所有这些都将立即重置。
我们在组件返回的代码中描述这些标志,将它们包装在
<label>
标记中并设置其属性。 他们的代码如下所示:
<label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.dietaryRestrictions.isLactoseFree} /> Lactose Free? </label>
dietaryRestrictions
对象的属性名称用作标志名称,而
this.state.dietaryRestrictions.isSomething
形式的
this.state.dietaryRestrictions.isSomething
其
checked
属性的值。
请注意,尽管将现有的
onChange
指定为
this.handleChange
事件处理程序,但我们必须对程序进行一些更改以确保程序正常运行。
看一下应用程序。
浏览器中的应用如您所见,页面上的标志已显示,但是该组件尚未包含确保其正常运行所需的所有机制。 让我们处理事件处理程序。
在这里,要使用标志,除了已经提取的那些属性之外,我们还需要从
event.target
对象中提取
type
和
checked
属性。 第一个需要检查元素的类型(标志是
checkbox
行所代表的类型),第二个需要找出复选框是选中还是未选中。 如果事实证明在用户与标志交互之后调用了处理程序,则我们使用特殊的状态设置过程。 我们将以与以前相同的方式处理其他控件的事件。
在更新状态时,应该牢记React是一个相当智能的系统,如果仅更新部分状态,它将自动在新状态中合并保持不变和更改的内容。 但是不能确定是否将以相同方式执行对象属性(即状态属性的值)的工作。 我们将把
handleChange
代码带到以下形式来验证这一点。 在这里,我们假设
dietaryRestrictions
对象的属性可以一次更改一次:
handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ dietaryRestrictions: { [name]: checked } }) : this.setState({ [name]: value }) }
如果您在浏览器中打开应用程序页面,则下载后立即看起来一切正常,例如,当您尝试在“
First Name
字段中输入
First Name
,一切都会像以前一样工作,但是当您尝试安装其中一个复选框时,将发出以下警告:
警告:组件正在将类型为受控的复选框更改为不受控制。 输入元素不应从受控状态切换到非受控状态(反之亦然)。 确定在组件的使用寿命期间使用受控或不受控制的输入元素。 更多信息: fb.me/react-control-components
为了正确更新
dietaryRestrictions
对象的内容,您可以使用
setState
函数形式自己创建状态的新版本。 如果我们必须管理大量标志,那么我们可能会这样做。 但是在这里我们将否则。 即,我们将使
dietaryRestrictions
对象的
dietaryRestrictions
属性成为属性,从而摆脱该对象:
this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false }
现在,我们将更改标志属性的设置,以摆脱
dietaryRestrictions
:
<label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label>
最后,编辑显示用户指定饮食限制信息的元素代码:
<p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p>
之后,我们将检查应用程序的运行状况。
浏览器中的应用如您所见,一切正常。
这是
App
组件的完整代码:
import React, {Component} from "react" class App extends Component { constructor() { super() this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false } this.handleChange = this.handleChange.bind(this) } handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value }) } render() { return ( <main> <form> <input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" /> <br /> <label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label> <br /> <select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select> <br /> <label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label> <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> <p>Your gender: {this.state.gender}</p> <p>Your destination: {this.state.destination}</p> <p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p> </main> ) } } export default App
总结
今天,您已经完成了表格上的实际工作。 然后,您重复了在以前的课程中学到的知识,我们希望您学到了一些新知识。 下次我们将讨论React应用程序的体系结构。
亲爱的读者们! 告诉我,完成这项实际工作难吗?
