如何使用React和语义UI创建多步表单
介绍
表单用于收集 Web 应用程序上的用户输入。 但是,您可能会发现自己需要从用户那里收集大量信息,这可能会导致大量字段。
一种解决方案是将表单分成多个部分(或步骤)。 每个部分在每个点收集某种类型的信息。
在本教程中,您将使用 React 和语义 UI 构建一个多步骤注册表单。 您可以通过为每个部分使用 React 组件来实现这一点。 然后,您可以通过操作状态来选择在每个步骤中呈现哪些组件。
先决条件
要完成本教程,您需要:
- Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
- 在开始本教程之前对 React 有一个很好的理解会很有帮助。 您可以通过阅读 如何在 React.js 系列中编写代码来了解有关 React 的更多信息。
本教程已使用 Node v14.0.0、npm v6.14.4、react v16.13.1、semantic-ui-react v0.88.2 和 semantic-ui-css v2.4.1 进行了验证.
第 1 步 — 使用语义 UI 初始化一个新的 React 项目
首先,您将使用 npx 来使用 create-react-app 来生成您的项目。
在您的终端中,运行以下命令:
npx create-react-app multistep-form
这将创建一个完全配置了开发环境的示例 React 应用程序。
接下来,切换到新创建的项目目录:
cd multistep-form
对于样式,您将使用 UI 框架 Semantic UI。 要在您的 React 应用程序中使用 Semantic UI,您将使用 Semantic UI React。 Semantic UI React 提供了可用于加速开发过程的预构建组件。
它还支持响应式网页设计,非常适合构建跨平台网站。
在您的终端中,运行以下命令:
npm install semantic-ui-react@0.88.2
接下来,您还将包括默认主题。
在您的终端中,运行以下命令:
npm install semantic-ui-css@2.4.1
要添加自定义语义 UI CSS,请打开 index.js 文件:
nano src/index.js
并添加以下 import:
src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import 'semantic-ui-css/semantic.min.css'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker';
现在 React 项目已经初始化并且你已经添加了必要的依赖项,你可以开始创建你的组件了。
第 2 步 — 创建组件
在本教程步骤中,您将添加创建五个组件:
MainForm.jsxUserDetails.jsxPersonalDetails.jsxConfirmation.jsxSuccess.jsx
首先,让我们编辑 App.js 来导入组件并渲染它们:
nano src/App.js
将 create-react-app 生成的所有样板代码替换为以下代码行:
src/App.js
import React, { Component } from 'react';
import { Grid } from 'semantic-ui-react';
import './App.css';
import MainForm from './components/MainForm';
class App extends Component {
render() {
return (
<Grid verticalAlign='middle' style={{ height: '100vh' }}>
<MainForm />
</Grid>
);
}
}
export default App;
注意: 如果您现在启动开发服务器,您将遇到错误,直到您完成编写和导入表单的所有组件。
在此代码中,您使用了 Semantic UI React 中的 Grid 组件,它通过使文本居中并添加填充来使其更具表现力。
您还导入并使用了 MainForm 组件。 让我们现在就开始吧。
构建 MainForm 组件
您将设置的第一个组件是 MainForm.jsx 组件,它将负责您应用程序中的大部分功能。
让我们在src目录下创建一个components文件夹:
mkdir src/components
然后创建一个 Mainform.jsx 文件:
nano src/components/MainForm.jsx
添加以下代码行:
src/components/MainForm.jsx
import React, { Component } from 'react';
import UserDetails from './UserDetails';
import PersonalDetails from './PersonalDetails';
import Confirmation from './Confirmation';
import Success from './Success';
此代码将导入依赖项。 它还将导入表单的四个部分:UserDetails、PersonalDetails、Confirmation 和 Success。 接下来您将构建这些组件。
然后,在导入下,为 MainForm 组件添加状态:
src/components/MainForm.jsx
// ...
class MainForm extends Component {
state = {
step: 1,
firstName: '',
lastName: '',
email: '',
age: '',
city: '',
country: ''
}
}
export default MainForm;
firstName、lastName、email、age、city、country是您感兴趣的信息字段在最终用户提供。
step 将是一个从 1 到 4 的数字。 这将允许您跟踪用户当前处于多步骤过程中的哪个步骤。
然后,添加 nextStep、prevStep 和 handleChange 函数:
src/components/MainForm.jsx
// ...
class MainForm extends Component {
// ...
nextStep = () => {
const { step } = this.state
this.setState({
step : step + 1
})
}
prevStep = () => {
const { step } = this.state
this.setState({
step : step - 1
})
}
handleChange = input => event => {
this.setState({[input]: event.target.value})
}
}
// ...
组件使用默认的 step in state 值初始化为 1,并呈现表单的第一部分。 然后,用户可以使用 prevStep 和 nextStep 函数在步骤之间来回跳转。 这些更新状态中 step 的值,以允许用户在渲染的组件之间切换。
handleChange 函数更新用户在状态内部提供的详细信息的值,与 prevStep 和 nextStep 函数一样,它将作为道具传递给子组件。 这将允许您传递实现的功能以在子组件中使用。
然后,添加 render 函数:
src/components/MainForm.jsx
// ...
class MainForm extends Component {
// ...
render() {
const { step } = this.state;
const { firstName, lastName, email, age, city, country } = this.state;
const values = { firstName, lastName, email, age, city, country };
switch(step) {
case 1:
return <UserDetails
nextStep={this.nextStep}
handleChange = {this.handleChange}
values={values}
/>
case 2:
return <PersonalDetails
nextStep={this.nextStep}
prevStep={this.prevStep}
handleChange = {this.handleChange}
values={values}
/>
case 3:
return <Confirmation
nextStep={this.nextStep}
prevStep={this.prevStep}
values={values}
/>
case 4:
return <Success />
}
}
}
// ...
多步表单使用 switch 语句,它从状态读取 step 并使用它来选择在每个步骤中呈现哪些组件。
在 Step 1 处,将渲染 UserDetails 组件。 在 Step 2 处,将渲染 PersonalDetails 组件。 在 Step 3,将渲染 Confirmation 组件。 在 Step 4 处,将渲染 Success 组件。
您的 MainForm 组件现已完成。
构建 UserDetails 组件
现在,让我们创建表单的第一部分。
创建一个 UserDetails.jsx 文件:
nano src/components/UserDetails.jsx
添加以下代码行:
src/components/UserDetails.jsx
import React, { Component } from 'react';
import { Grid, Header, Segment, Form, Button } from 'semantic-ui-react';
class UserDetails extends Component {
saveAndContinue = (e) => {
e.preventDefault();
this.props.nextStep();
}
render() {
const { values } = this.props;
return (
<Grid.Column style={{ maxWidth: 450 }}>
<Header textAlign='center'>
<h1>Enter User Details</h1>
</Header>
<Form>
<Segment>
<Form.Field>
<label>First Name</label>
<input
placeholder='First Name'
onChange={this.props.handleChange('firstName')}
defaultValue={values.firstName}
/>
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input
placeholder='Last Name'
onChange={this.props.handleChange('lastName')}
defaultValue={values.lastName}
/>
</Form.Field>
<Form.Field>
<label>Email Address</label>
<input
type='email'
placeholder='Email Address'
onChange={this.props.handleChange('email')}
defaultValue={values.email}
/>
</Form.Field>
</Segment>
<Segment>
<Button onClick={this.saveAndContinue}>Save And Continue</Button>
</Segment>
</Form>
</Grid.Column>
);
}
}
export default UserDetails;
这将创建一个表单,用于收集用户的名字、姓氏和电子邮件地址。
然后,saveAndContinue 函数负责在用户填写完详细信息后将其路由到下一个组件。
您会注意到您已经调用了作为道具提供给组件的 nextStep 函数。 每次调用此函数时,都会更新父组件(MainForm)的状态。 您还调用了 handleChange 并提供了要在每个输入元素上更新的每个字段的名称。
您可能还注意到,每个输入字段都提供了一个 defaultValue,它从 MainForm 组件的状态中选择。 这允许它在用户从另一个步骤返回到一个步骤的情况下选择状态中的更新值。
您的 UserDetails 组件现已完成。
构建 PersonalDetails 组件
现在,让我们创建第二个部分,它收集用户的个人信息。
创建一个 PersonalDetails.jsx 文件:
nano src/components/PersonalDetails.jsx
添加以下代码行:
src/components/PersonalDetails.jsx
import React, { Component } from 'react';
import { Grid, Header, Segment, Form, Button } from 'semantic-ui-react';
class PersonalDetails extends Component {
saveAndContinue = (e) => {
e.preventDefault();
this.props.nextStep();
}
back = (e) => {
e.preventDefault();
this.props.prevStep();
}
render() {
const { values } = this.props;
return (
<Grid.Column style={{ maxWidth: 450 }}>
<Header textAlign='center'>
<h1>Enter Personal Details</h1>
</Header>
<Form>
<Segment>
<Form.Field>
<label>Age</label>
<input placeholder='Age'
onChange={this.props.handleChange('age')}
defaultValue={values.age}
/>
</Form.Field>
<Form.Field>
<label>City</label>
<input placeholder='City'
onChange={this.props.handleChange('city')}
defaultValue={values.city}
/>
</Form.Field>
<Form.Field>
<label>Country</label>
<input placeholder='Country'
onChange={this.props.handleChange('country')}
defaultValue={values.country}
/>
</Form.Field>
</Segment>
<Segment textAlign='center'>
<Button onClick={this.back}>Back</Button>
<Button onClick={this.saveAndContinue}>Save And Continue</Button>
</Segment>
</Form>
</Grid.Column>
)
}
}
export default PersonalDetails;
此部分收集用户的年龄和位置。 总体功能类似于用户详细信息部分,只是添加了 Back 按钮,该按钮将通过从道具调用 prevStep 将用户带回到上一步。
您的每个组件中都有 back 和 saveAndContinue 函数将 event(e) 作为参数,并在这些函数中调用 event.preventDefault() 以停止表单每次用户提交时重新加载,这是表单中的默认行为。
您的 PersonalDetails 组件现已完成。
构建 Confirmation 组件
现在,让我们创建表单的最后一部分,用户确认他们提供给应用程序的详细信息是正确的。
创建一个 Confirmation.jsx 文件:
nano src/components/Confirmation.jsx
添加以下代码行:
src/components/Confirmation.jsx
import React, { Component } from 'react';
import { Grid, Header, Segment, Button, List } from 'semantic-ui-react';
class Confirmation extends Component {
saveAndContinue = (e) => {
e.preventDefault();
this.props.nextStep();
}
back = (e) => {
e.preventDefault();
this.props.prevStep();
}
render() {
const { values: { firstName, lastName, email, age, city, country } } = this.props;
return (
<Grid.Column style={{ maxWidth: 450 }}>
<Header textAlign='center'>
<h1>Confirm your Details</h1>
<p>Click Confirm if the following details have been correctly entered</p>
</Header>
<Segment>
<List divided relaxed>
<List.Item>
<List.Icon name='users' size='large' />
<List.Content>First Name: {firstName}</List.Content>
</List.Item>
<List.Item>
<List.Icon name='users' size='large' />
<List.Content>Last Name: {lastName}</List.Content>
</List.Item>
<List.Item>
<List.Icon name='mail' size='large' />
<List.Content>Email: {email}</List.Content>
</List.Item>
<List.Item>
<List.Icon name='calendar' size='large' />
<List.Content>Age: {age}</List.Content>
</List.Item>
<List.Item>
<List.Icon name='marker' size='large' />
<List.Content>Location: {city}, {country}</List.Content>
</List.Item>
</List>
</Segment>
<Segment textAlign='center'>
<Button onClick={this.back}>Back</Button>
<Button onClick={this.saveAndContinue}>Confirm</Button>
</Segment>
</Grid.Column>
)
}
}
export default Confirmation;
这将创建一个显示用户输入的所有详细信息的部分,并要求他们在提交之前确认详细信息。 这通常是您对后端进行最终 API 调用以提交和保存数据的地方。
由于这是一个演示,因此 Confirm 按钮实现了与您在之前的组件中使用的相同的 saveAndContinue 功能。 但是,在实际场景中,您将实现一个不同的提交函数来处理最终提交并保存数据。
您的 Confirmation 组件现已完成。
构建 Success 组件
项目中的下一个也是最后一个组件是 Success 组件,它将在用户成功保存其信息时呈现。
创建一个 Confirmation.jsx 文件:
nano src/components/Success.jsx
添加以下代码行:
src/components/Success.jsx
import React, { Component } from 'react';
import { Grid, Header } from 'semantic-ui-react';
class Success extends Component {
render() {
return (
<Grid.Column style={{ maxWidth: 450 }}>
<Header textAlign='center'>
<h1>Details Successfully Saved</h1>
</Header>
</Grid.Column>
)
}
}
export default Success;
当用户到达表单的最后一步时,这将显示 'Details Successfully Saved' 消息。
您已完成多步骤表单的所有组件。
第 3 步 — 试用表格
现在,在 Web 浏览器中查看表单。
使用终端窗口并确保您位于项目目录中。 使用以下命令启动项目:
npm start
在 Web 浏览器中导航到 localhost:3000。
您的应用程序将显示 Step 1 - Enter User Details:
输入您的信息并单击保存并继续后,您将被引导至步骤2 - 输入个人详细信息:
输入您的信息并单击保存并继续后,您将被引导至步骤3 - 确认您的详细信息:
点击确认后,会跳转到Step 4 - Success。
你现在在 React 中有一个工作的多步骤表单。
结论
当您需要将表单分解为多个部分时,多步表单非常有用。 它们还可以让您在进行下一步之前在每个步骤中执行表单验证。
使用 switch 语句在步骤之间进行路由消除了对路由器的需要,这意味着您可以将表单插入其他组件而无需调整路由。
如有必要,还可以在步骤之间设置 API 调用,这开辟了许多新的可能性。
还可以通过添加Redux等状态管理工具来更好地处理状态。
如果您想了解有关 React 的更多信息,请查看 我们的 React 主题页面 以获取练习和编程项目。