如何动态构建 UI
介绍
React 的组件驱动方法使我们可以轻松构建动态 UI 组件。您是否曾经想知道 Wordpress 和 Drupal 等 CMS 如何使用页面构建器动态构建 UI?好吧,这就是我们在本指南中要学习的内容;当然,我们将在 React 生态系统的开发环境中工作。
在本指南中,我们将探索如何使用 CMS Rest API 来提供“JSON 化”版本的 UI。更具体地说,我们将动态构建表单及其组件。
以下是来自服务器的 JSON 响应:
{
"form_heading": "Contact Form",
"fields": [
{
"label": {
"text": "Name"
},
"input": {
"type": "text",
"name": "name",
"validations": {
"required": true,
"minlength": 3,
"maxlength": 60
}
}
},
{
"label": {
"text": "Email"
},
"input": {
"type": "email",
"name": "email",
"validations": {
"required": true
}
}
},
{
"label": {
"text": "Message"
},
"input": {
"type": "textarea",
"name": "message",
"validations": {
"required": true,
"minlength": 30,
"maxlength": 255
}
}
}
],
"submit_button": {
"text": "Submit"
}
}
使用 create-react-app 启动项目
运行以下命令使用 create-react-app 创建 React 项目:
create-react-app dynamic-form
让我们创建表单组件
在src文件夹中创建一个<ContactForm />组件,并添加以下代码以从服务器获取数据。如果您不熟悉浏览器 Fetch API,您可以在我之前的指南《您需要了解的有关 Axios 的所有信息》中找到更多信息。
const SERVER_URL = "https://61m46.sse.codesandbox.io"; // enter your server URL here
class ContactForm extends Component {
constructor(props) {
super(props);
this.state = {
form: {}
};
}
componentDidMount() {
fetch(`${SERVER_URL}/forms/1`)
.then(res => res.json())
.then(data => this.setState({ forms: data }));
}
render() {
return <div>{JSON.stringify(this.state.forms)}</div>;
}
}
渲染字段的函数
让我们创建一个实用函数,它将根据字段类型为我们呈现输入字段。
renderField = field => {
const { input } = field;
const { validations } = input;
switch (field.input.type) {
case "textarea":
return (
<textarea
type={input.type}
name={input.name}
onChange={this.handleInput}
value={this.state[field.name]}
minLength={validations.minlength}
maxLength={validations.maxlength}
required={validations.required}
rows={input.rows}
id={input.name}
/>
);
default:
return (
<input
type={input.type}
name={input.name}
onChange={this.handleInput}
value={this.state[field.name]}
minLength={validations.minlength}
maxLength={validations.maxlength}
required={validations.required}
id={input.name}
/>
);
}
};
我们使用switch和case语句根据 JSON 响应中指定的字段输入类型返回相应的字段。
为了处理输入的变化,我们将编写一个onChange处理函数,将状态中的输入值存储为键值对,其中键是输入字段的名称。
class ContactForm extends Component {
// ...
handleInput = e =>
this.setState({ [e.currentTarget.name]: e.currentTarget.value });
render() {
// ...
}
}
让我们渲染表单
在组件的render()函数中,我们将循环遍历每个字段并使用renderField()实用函数进行渲染。
class ContactForm extends Component {
// ...
render() {
const { form } = this.state;
if (Object.keys(form).length < 1) {
return "Loading...";
}
return (
<>
<h1>{form.form_heading}</h1>
<div>
<form onSubmit={() => console.log(this.state)}>
{form.fields.map(field => (
<div className="input-group" key={field.input.name}>
<label for={field.input.name}>{field.label.text}</label>
{this.renderField(field)}
</div>
))}
<button type="submit">{form.submit_button.text}</button>
</form>
</div>
</>
);
}
}
在 index.js 文件中导入表单组件
import ContactForm from "./ContactForm";
function App() {
return (
<div className="App">
<ContactForm />
</div>
);
}
完整代码
ContactForm.js 文件
import React, { Component } from "react";
const SERVER_URL = "https://61m46.sse.codesandbox.io"; // enter your server URL here
class ContactForm extends Component {
constructor(props) {
super(props);
this.state = {
form: {}
};
}
componentDidMount() {
fetch(`${SERVER_URL}/forms/1`)
.then(res => res.json())
.then(data => this.setState({ form: data }));
}
handleInput = e =>
this.setState({ [e.currentTarget.name]: e.currentTarget.value });
renderField = field => {
const { input } = field;
const { validations } = input;
switch (field.input.type) {
case "textarea":
return (
<textarea
type={input.type}
name={input.name}
onChange={this.handleInput}
value={this.state[field.name]}
minLength={validations.minlength}
maxLength={validations.maxlength}
required={validations.required}
rows={input.rows}
id={input.name}
/>
);
default:
return (
<input
type={input.type}
name={input.name}
onChange={this.handleInput}
value={this.state[field.name]}
minLength={validations.minlength}
maxLength={validations.maxlength}
required={validations.required}
id={input.name}
/>
);
}
};
render() {
const { form } = this.state;
if (Object.keys(form).length < 1) {
return "Loading...";
}
return (
<>
<h1>{form.form_heading}</h1>
<div>
<form onSubmit={() => console.log(this.state)}>
{form.fields.map(field => (
<div className="input-group" key={field.input.name}>
<label for={field.input.name}>{field.label.text}</label>
{this.renderField(field)}
</div>
))}
<button type="submit">{form.submit_button.text}</button>
</form>
</div>
</>
);
}
}
export default ContactForm;
index.js 文件
import React from "react";
import ReactDOM from "react-dom";
import ContactForm from "./ContactForm";
import "./styles.css";
function App() {
return (
<div className="App">
<ContactForm />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
style.css 文件
.App {
font-family: sans-serif;
}
.input-group {
margin-bottom: 10px;
}
.input-group label {
display: block;
margin-bottom: 5px;
}
button {
border: none;
padding: 8px 24px;
}
奖励部分 - 让我们添加一个选择字段
让我们看看如何动态创建一个选择输入字段。
对于选择字段,我们可以假设以下 JSON 响应:
{
"label": {
"text": "Role"
},
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~