gpt4 book ai didi

javascript - ReactJS表单组件的最佳实践

转载 作者:IT王子 更新时间:2023-10-29 03:20:52 25 4
gpt4 key购买 nike

我正在寻找使ReactJS组件负责用户编辑给定实体的表单的最佳实践。这里的例子非常简单。在许多情况下,实际的表单将具有更多的字段和更多的GUI功能。

React.createClass({
getInitialState: function() {
return {
entity: {
property1: null,
property2: null
}
};
},

handleChange: function(e) {
var entity = this.state.entity;

switch(e.target.name) {
case 'property1':
entity.property1 = e.target.value;
break;
case 'property2':
entity.property2 = e.target.value;
break;
}

this.setState({
entity: entity
});
},

render: function() {
return (
<div className="entity-form">
<form onChange={this.handleChange}>
<input type="text" name="property1" value={this.state.entity.property1} />
<br />

<textarea name="property2" value={this.state.entity.property2}></textarea>
<br />
</form>
</div>
);
}
});

表单的字段直接编辑实体对象,然后可以将其保存到RESTful api。我希望在用户更改字段时更新组件,以便GUI可以根据键入期间的输入使用react(例如验证,信息等)。

从理论上讲,我可以让整个状态对象代表正在编辑的实体,因此该实体的每个属性都是第一级状态变量。但是,我希望能够为GUI函数和与组件将要执行的操作有关的其他事情添加其他状态变量,因此我希望实体对象是一个状态变量,例如上面的“实体”状态变量。该对象当然可以是一些更复杂的对象,例如Backbone模型或类似对象,但是在此简化示例中,我仅使用具有所需属性的简单对象。

因此,在寻求为此目的制造React组件的最佳实践方法时,我有一些问题:
  • Prop 或状态。

  • 在这种情况下,我选择将带有表单内容的实体对象放在状态变量中而不是prop中。这是为了能够在表单输入期间更新对象,而不必调用父对象并更新 Prop 。就我的React经验而言,这将是此类表单组件的最佳实践。
  • 受控或不受控制的输入。

  • 在上面的简化示例中,我使用受控输入。这将导致在每次更改时更新状态并重新呈现组件(就像在文本字段中输入的每个字符一样)。这是最佳做法吗?好消息是,该组件可以完全控制发生的事情,而不是使用defaultValue参数,并且在某些事件(例如用户按下保存按钮)下,该组件可以提取值,更新实体并将其保存到服务器。对于在这种情况下应使用受控输入还是不受控制输入,是否有任何原因(或观点)?

    表单或每个输入的
  • onChange

    该示例在form标记上具有onChange,它使每次更改表单中的任何字段时都调用handleChange方法。但是,由于输入是受控的(具有值参数),因此React提示输入字段没有onChange属性。这是否意味着在表单标签上使用通用的onChange是不好的做法,我应该将其删除并将onChange放在每个单独的字段上?
  • 更新单个属性

  • 在上面的示例中,我基于要更新的​​输入字段(当调用handleChange时)使用开关。我想我可以改为确保所有字段名称都与实体的属性名称同步,并且我可以基于事件中字段的名称(e.target.name)在handleChange中设置实体对象的属性。但是,即使大多数字段仅直接更新实体属性,也很难使每个字段具有单独的需求。我猜想Alternativ是一个具有基于输入名称的默认块设置的开关,对于需要其他更新方式(例如,在实体上对其进行设置之前进行过滤的值)的任何字段,都使用case块。如果您知道通过这种方式处理现场更新的更好方法,请对此发表评论。
  • 更新状态实体

  • 此示例的一个大问题是实体对象的更新方式。由于handleChange中的实体变量已从当前状态设置为实体对象,因此这只是一个指针,更新实体变量将更改对象的状态。 React页面说您永远不要直接更新状态。原因之一是我在调用setState之前以这种方式更新状态时遇到的事情。如果具有shouldComponentUpdate方法,则prevState将包含新状态,因为发送到shouldComponentUpdate的prevState参数的内容基于调用setState时的状态。据我所知,没有简单的方法可以在javascript中克隆对象。所以问题是,当拥有整个对象时,我需要更新(而不是触摸对象中的其他值)的属性,而不是仅运行单个状态变量的setState,那么在不引起这些种类的情况下做到这一点的最佳方法是什么状态混淆?

    最佳答案

  • 任何要更改的内容都会进入State状态。
  • 如果要加载现有实体并对其进行编辑,则需要受控输入,并希望相应地设置值。在大多数情况下(下拉菜单之外),我倾向于远离defaultValue
  • 这与您先前的问题联系在一起。如果指定一个值,则使用的是受控输入,并且必须为任何受控输入提供onChange处理程序,否则将其设置为固定值。受控输入的好处是用户无法编辑它们,因此,如果您锁定了某些属性(出于安全性考虑,可能出于只读目的),那么当用户尝试保存时,即使他们直接编辑了HTML,React也应来自vDOM表示形式的属性值(在这里可能是错误的,但我相信我之前已经对此进行过测试)。无论如何,您必须直接在受控输入上设置onChange。至于使用事件查询(在表单级别),这对于许多事件根本不是一个坏习惯,这只是一个特定的场景(受控输入),您需要为每个元素指定onChange事件。
  • 不能完全确定这个问题是什么,但是我使用了refs而不是target.name。
  • 所以,您是对的,因为您永远不要直接更改状态,这对文档来说是一个棘手的问题。 React将直接更改状态,它将通过setState在实现中进行更改。如果在此方法调用之外更改状态,则会发生意外情况,并会引发错误。

  • shouldComponentUpdate仅做浅层比较,但是这里有一些解决方案。

    一种是对对象进行字符串化处理,这是一种快速而肮脏的对象比较,不建议您这样做,但是可以。

    一个更好的解决方案(我与React + Flux一起使用过)是实现一个propertyChanged bool 型,只需在shouldComponentUpdate中进行检查即可。

    现在,这将需要您知道在事情发生变化时进行设置,即,您已在对象图中更深入地进行了更改。说propertyOne是一个对象,该对象的属性在handleChange方法中被更改。您可以根据需要验证输入,然后将propertyChanged = true设置为 ,然后需要实现componentDidUpdate 。我们在这里进行假设,但是如果组件已更新,则将propertyChanged设置回false,这样就不会再触发不需要的更新了。我希望这是有道理的。有点像单向notifyPropertyChanged。

    我提供了一个简短的示例,说明我可能会为更动态的实现而做的事情,该实现允许您向对象添加更多属性(此实现中只有较浅的属性,显然您可以编写更可靠的解决方案)。让我知道您是否还有其他问题,或者我没有回答。

    http://jsfiddle.net/rpv9trhh/
    var e = {
    prop1: 'test',
    prop2: 'wee',
    prop3: 'another property',
    propFour: 'Oh yeah!'
    };

    var FormComp = React.createClass({
    getInitialState: function(){
    return {
    entity: this.props.entity
    }
    },
    render: function() {

    var ent = this.state.entity;
    var that = this;
    var inputs = [];

    for(var key in ent){
    inputs.push(<input
    key={key}
    style={{display:'block'}}
    type="text"
    ref={key} onChange={that._propertyChanged.bind(null, key)}
    value={ent[key]} />)
    }

    return <form>
    {inputs}
    <input
    type="button"
    onClick={this._saveChanges}
    value="Save Changes" />
    </form>;
    },
    _propertyChanged: function(propName) {
    var nextProp = this.refs[propName].getDOMNode().value;
    var nextEntity = this.state.entity;
    nextEntity[propName] = nextProp;

    this.setState({
    entity: nextEntity
    });
    },
    _saveChanges: function() {
    var updatedEntity = this.state.entity;

    for(var key in updatedEntity){
    alert(updatedEntity[key]);
    }

    //TODO: Call to service to save the entity, i.e.
    ActionCreators.saveEntity(updatedEntity);
    }
    });

    React.renderComponent(<FormComp entity={e} />, document.body);

    关于javascript - ReactJS表单组件的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26626454/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com