我有一个基于反应的表单,其中包含超过10个字段,对于这10个字段,有(受控组件)。
这些input字段大多数都是text类型的,但其他类型的字段将在稍后添加。
问题是,我需要编写10更改处理程序,以便它们正确设置状态,然后在构造函数中为每个处理程序添加方法绑定。
我对此反应很新,可能不知道正确的方法和技巧。
请指导我如何改进我目前的代码结构,避免编写锅炉板和重复错误的代码。
我现在的注册内容如下-
export default class Register extends Component {
constructor(props){
super(props);
this.state = {
regName : '',
regAdd1 : '',
regAdd2 : '',
regState : '',
regZipCode : '',
regCity : '',
regPhone : ''
};
// add bindings .... ugh..
this.changeRegAdd1 = this.changeRegAdd1.bind(this);
this.changeRegAdd2 = this.changeRegAdd2.bind(this);
//Similary binding for other handlers...
}
// add individual field change handlers ... ugh...
changeRegName(e) {
this.setState({regName:e.target.value});
}
changeRegAdd1(e) {
this.setState({regAdd1:e.target.value});
}
changeRegAdd2(e) {
this.setState({regAdd2:e.target.value});
}
changeRegState(e) {
this.setState({regState:e.target.value});
}
// Similary for other change handler ....
handleSubmit(e) {
e.preventDefault();
// validate then do other stuff
}
render(){
let registrationComp = (
<div className="row">
<div className="col-md-12">
<h3>Registration Form</h3>
<fieldset>
<div className="form-group">
<div className="col-xs-12">
<label htmlFor="regName">Name</label>
<input type="text" placeholder="Name"
onChange={this.changeregName} value = {this.state.regName} className="form-control" required autofocus/>
</div>
</div>
<div className="form-group">
<div className="col-xs-12">
<label htmlFor="regAdd1">Address Line1</label>
<input
type = "text"
placeholder = "Address Line1"
onChange = {this.changeregAdd1}
value = {this.state.regAdd1}
className = "form-control"
required
autofocus
/>
<input
type = "text"
placeholder = "Address Line2"
onChange = {this.changeregAdd2}
value = {this.state.regAdd2}
className = "form-control"
required
autofocus
/>
</div>
</div>
<div className="form-group">
<div className="col-xs-6">
<label htmlFor="regState">State</label>
<input
type = "text"
placeholder = "State"
onChange = {this.changeregState}
value = {this.state.regState}
className = "form-control"
required
autofocus
/>
</div>
<div className="col-xs-6">
<label htmlFor="regZipCode">Zip Code</label>
<input
type = "text"
placeholder = "Zip Code"
onChange = {this.changeregZipCode}
value = {this.state.regZipCode}
className = "form-control"
required
autofocus
/>
</div>
</div>
<div className="form-group">
<div className="col-xs-12">
<label htmlFor="regCity">City</label>
<input
type = "text"
placeholder = "City"
title = "City"
onChange = {this.changeregCity}
value = {this.state.regCity}
className = "form-control"
required
autofocus
/>
</div>
</div>
{/* other form fields */}
</fieldset>
</div>
</div>
);
return registrationComp;
}
}发布于 2017-07-04 16:06:53
还有很多其他的方法,我可能不知道。
但是,我更喜欢对某些类型的公共字段(如<input type of text /> )进行公共方法中的更改处理。
这是一个样本输入字段-
<input
onChange = {this.onChange}
value = {this.state.firstName}
type = "text"
name = {"firstName"}
/>我将状态的字段名和输入的" name "属性保持相同。之后,我为所有这些字段编写了一个公共更改处理程序。
只需在更改处理程序中编写一行。
onChange(e) {
this.setState({[e.target.name]: e.target.value});
}我使用es6的动态属性设置from string作为属性名。
{ ["propName] : propValue }.为了避免为react组件中的方法编写手动绑定,您可以遵循以下两种方法-
在组件中创建这样的方法。
_bind(...methods) {
methods.forEach( (method) => this[method] = this[method].bind(this) );
}使用_bind绑定您的方法。
constructor(props){
super(props);
this.state = {
regName : '',
regAdd1 : '',
regAdd2 : '',
regState : '',
regZipCode : '',
regCity : '',
regPhone : ''
};
// add bindings .... ugh..
//this.changeRegAdd1 = this.changeRegAdd1.bind(this);
//this.changeRegAdd2 = this.changeRegAdd2.bind(this);
//Similary binding for other handlers...
this._bind(
'changeRegName',
'changeReg1' , 'changeRegAdd2'
// and so on.
);
}编辑:
添加验证-
\*required ):null;});返回{错误,isValid :isEmptyObj(错误) };} isFormValid() { const { errors,isValid }= this.validateInput();if (!isValid) { this.setState({错误});}返回isValid;} onSubmit(e) { e.preventDefault();this.setState({errors:{}});if (this.isFormValid()) { //执行表单提交}}我已经习惯了实用的方法isEmpty,isEmptyObj。他们只是检查对象是空的还是未定义的,或者字段是空的。
我希望这能帮到你。
发布于 2017-07-04 16:34:44
您可以创建一个高阶组件来处理其中的许多问题。如果你愿意的话,剩馀形式有一个很好的模式,你可以模仿它。
从本质上讲,您将得到类似于以下内容的结果(我根本没有测试过这一点,但它应该运行得很好):
export class Field extends Component {
handleChange = (event) => this.props.onChange(this.props.name, event.target.value)
render() {
const InputComponent = this.props.component
const value = this.props.value || ''
return (
<InputComponent
{...this.props}
onChange={this.handleChange}
value={value}
/>
}
}
export default function createForm(WrappedComponent) {
class Form extends Component {
constructor() {
super()
this.state = this.props.initialValues || {}
this.handleChange = this.handleChange.bind(this)
}
handleChange(name, value) {
this.setState({
[name]: value,
})
}
render() {
return (
<WrappedComponent
{...this.state}
{...this.props}
// pass anything you want to add here
onChange={this.handleChange}
values={this.state}
/>
)
}
}
return Form
}然后,您可以根据需要增强这个组件(添加焦点、模糊、提交处理程序等)。你可以用这样的方法:
import createForm, { Field } from './createForm'
// simplified Registration component
export class Registration extends Component {
render() {
return (
<form>
<Field
component="input"
name="name"
onChange={this.props.onChange}
type="text"
value={this.props.values.name}
/>
</form>
)
}
}
export default createForm(Registration)您可能会疯狂地进入上下文,这样您就不必手动传递值和函数,但我至少会远离它,直到您更加熟悉React为止。
另外,如果您不想手动绑定函数,那么如果使用babel,可以使用类属性变换。然后,Form组件的外观将如下所示:
class Form extends Component {
state = this.props.initialValues || {}
handleChange = (name, value) => this.setState({
[name]: value,
})
render() {
return (
<WrappedComponent
{...this.state}
{...this.props}
onChange={this.handleChange}
values={this.state}
/>
)
}
}发布于 2017-07-04 19:44:13
看看它是如何在NeoForm中完成的
onChange处理程序onBlur)和表单(例如onSubmit)验证它在内部使用context,非常小且模块化的源代码很容易理解。
https://stackoverflow.com/questions/44910295
复制相似问题