React.js - 从 JSON 模式创建输入元素

IT技术 javascript json reactjs
2021-05-18 19:55:30

我正在寻找有关在 React 中使用组件映射从 JSON 动态创建元素的最佳方法的建议。

我认为我们可以将每个输入类型作为一个单独的组件类,并构造传入的元素props并绑定更改。

例如 JSON:

    {
        "type": "text",
        "name": "FirstName",                    
        "class": "text",
        "placeholder": "Enter first name"
    },
    {
        "type": "text",
        "name": "Surname",                  
        "class": "text",
        "placeholder": "Enter surname"
    },

react:

class InputText extends React.Component {
  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  render() {
    return (
      <div className={className}>
        <label htmlFor={this.props.name}>{this.props.title}</label>
        <input
          onChange={this.changeValue}
          name={this.props.name}
          type={this.props.type}
          value={this.props.value}
        />
      </div>
    );
  }
}

关于迭代(和验证)JSON 中每个项目的最佳方法有什么建议吗?我在正确的轨道上吗?谢谢!

3个回答

您需要一个map覆盖数据并返回InputTexts集合的组件。我在这里称它为Main

class Main extends React.Component {
  render() {

    // Map over the data and return the completed component
    // On each iteration pass in the object data as `params`.
    // You can deconstruct this in the `InputText` component
    return data.map((input, i) => {
      return <InputText key={i} params={input} />
    });
  }
}

现在,您可以通过解构this.props.params并使用这些变量来填充组件来获取组件中的这些参数。

class InputText extends React.Component {

  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  changeValue() {
    console.log('Placeholder to prevent bug');
  }

  render() {

   // Use destructuring to grab the individual properties from params
   const { type, name, classname, placeholder } = this.props.params;

    // Use those properties in the returned component elements
    return (
      <div className={classname}>
        <label htmlFor={name}>Test</label>
        <input
          onChange={this.changeValue}
          name={name}
          type={type}
          placeholder={placeholder}
        />
      </div>
    );
  }
}

演示

输入文本.jsx

在交互时,每个人InputText都会提出onChange说哪个输入字段被编辑以及它的当前值是多少。

import * as React from 'react';

export class InputText extends React.Component {
  onChange = (e) => {
    const {onChange, name} = this.props;
    const {value} = e.target;
    if (onChange) {
      onChange(name, value);
    }
  }

  render() {
    const {name, title, type, placeholder, className, value} = this.props;
    return (
      <div className={className}>
        <label htmlFor={name}>{title}</label>
        <input
          placeholder={placeholder}
          name={name}
          type={type}
          value={value}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

表单.jsx

在这里,我们维护所有输入的状态。奇怪的reduce是用输入名称作为对象属性初始化状态的形状。

// initial state
{
  "FirstName": "",
  "Surname": ""
}

编辑后this.setState({[name]: value}),关联的属性会更新。

import * as React from 'react';
import { InputText } from './InputText';

const inputs = [{
  "type": "text",
  "title": "some title",
  "name": "FirstName",
  "class": "text",
  "placeholder": "Enter first name"
}, {
  "type": "text",
  "title": "some other title",
  "name": "Surname",
  "class": "text",
  "placeholder": "Enter surname"
}];

export class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = inputs.reduce((acc, input) => {
      return {...acc, [input.name]: ''};
    }, {})
  }

  onChange = (name, value) => {
    this.setState({[name]: value});
  }

  render() {
    const list = inputs.map(input => {
      return (
        <InputText
          value={this.state[input.name]}
          key={input.name}
          type={input.type}
          name={input.name}
          title={input.title}
          className={input.class}
          placeholder={input.placeholder}
          onChange={this.onChange}
      />
      );
    });

    return (
      <form>
        {list}
      </form>
    );
  }
}

假设您要遍历的 JSON 以数组形式提供,您可以执行以下操作。它将为每个 JSON 创建一个标签和输入元素。

render() {
  return (
    <div className={className}>
      {
      this.props.yourArray.map(value=>(
        <label htmlFor={value.name}>{value.title}</label>
        <input
          onChange={this.changeValue}
          name={value.name}
          type={value.type}
          value={value.value}
        />
      ))
      }
    </div>
  );
}