React.js:使用一个onChange处理程序识别不同的输入

T3d*_*b0t 132 javascript reactjs

很好奇接近这个的正确方法是:

var Hello = React.createClass({
getInitialState: function() {
    return {total: 0, input1:0, input2:0};
},
render: function() {
    return (
        <div>{this.state.total}<br/>
            <input type="text" value={this.state.input1} onChange={this.handleChange} />
            <input type="text" value={this.state.input2} onChange={this.handleChange} />
        </div>
    );
},
handleChange: function(e){
    this.setState({ ??? : e.target.value});
    t = this.state.input1 + this.state.input2;
    this.setState({total: t});
}
});

React.renderComponent(<Hello />, document.getElementById('content'));
Run Code Online (Sandbox Code Playgroud)

显然你可以创建单独的handleChange函数来处理每个不同的输入,但这不是很好.类似地,您可以为单个输入创建一个组件,但我想看看是否有这样的方法.

Ros*_*len 154

我建议坚持使用像Elements name上的标准HTML属性input来识别您的输入.此外,您不需要将"total"保持为状态中的单独值,因为它可以通过在您的州中添加其他值来组合:

var Hello = React.createClass({
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },
    render: function() {
        const total = this.state.input1 + this.state.input2;

        return (
            <div>{total}<br/>
                <input type="text" value={this.state.input1} name="input1" onChange={this.handleChange} />
                <input type="text" value={this.state.input2} name="input2" onChange={this.handleChange} />
            </div>
        );
    },
    handleChange: function(e) {
        this.setState({[e.target.name]: e.target.value});
    }
});

React.renderComponent(<Hello />, document.getElementById('content'));
Run Code Online (Sandbox Code Playgroud)

  • @ T3db0t这个ES6语法有效:`this.setState({[e.target.name]:e.target.value});` (23认同)
  • 我最初尝试这样做,但是setState({e.target.name ...不起作用 - 这是一个语法错误.你必须使用obj [e.target.name]和setState创建一个临时对象.这种工作,但似乎在状态对象更新中有某种延迟. (3认同)
  • @ericgrosse bind在这种情况下并不是更好,因为你创建了许多不必要的函数.另外,如果需要,您可以在不同类型的元素上使用数据属性 (3认同)
  • 使用bind是更好的方法.如果将onChange处理程序附加到没有name属性的元素(例如div),则此方法不起作用. (2认同)

fia*_*jaf 106

您可以使用该.bind方法预先构建handleChange方法的参数.它会是这样的:

  var Hello = React.createClass({
    getInitialState: function() {
        return {input1:0, 
                input2:0};
    },
    render: function() {
      var total = this.state.input1 + this.state.input2;
      return (
        <div>{total}<br/>
          <input type="text" value={this.state.input1} 
                             onChange={this.handleChange.bind(this, 'input1')} />
          <input type="text" value={this.state.input2} 
                             onChange={this.handleChange.bind(this, 'input2')} />
        </div>
      );
    },
    handleChange: function (name, e) {
      var change = {};
      change[name] = e.target.value;
      this.setState(change);
    }
  });

  React.renderComponent(<Hello />, document.getElementById('content'));
Run Code Online (Sandbox Code Playgroud)

(我也是total在渲染时计算的,因为这是建议的事情.)

  • 只需快速提醒一下,`this.handleChange.bind(...)`创建一个新函数.如果您将`shouldComponentUpdate`与`PureRenderMixin`或类似的东西一起使用,它将会中断.当单个值更改时,将重新呈现所有输入组件. (13认同)
  • 如果将`handleChange`的实现更改为`handleChange(name){return event => this.setState({name:event.target.value}); 你可以传递"相同"的函数(不会创建新的函数,因为它使用`.bind()`然后,你可以传递这样的函数:`this.handleChange("input1")` (5认同)

Chr*_*ies 37

onChange事件冒泡......所以,你可以这样做:

// A sample form
render () {
  <form onChange={setField}>
    <input name="input1" />
    <input name="input2" />
  </form>
}
Run Code Online (Sandbox Code Playgroud)

并且您的setField方法可能如下所示(假设您使用的是ES2015或更高版本:

setField (e) {
  this.setState({[e.target.name]: e.target.value})
}
Run Code Online (Sandbox Code Playgroud)

我在几个应用程序中使用类似的东西,它非常方便.


Seb*_*ber 11

不推荐的解决方案

valueLink/checkedLink从核心React 中弃用,因为它让一些用户感到困惑.如果您使用最新版本的React,此答案将无效.但如果你喜欢它,你可以通过创建自己的Input组件轻松地模拟它

老答案内容:

使用React的双向数据绑定助手可以更轻松地实现您想要实现的目标.

var Hello = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },

    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
            <div>{total}<br/>
                <input type="text" valueLink={this.linkState('input1')} />;
                <input type="text" valueLink={this.linkState('input2')} />;
            </div>
        );
    }

});

React.renderComponent(<Hello />, document.getElementById('content'));
Run Code Online (Sandbox Code Playgroud)

容易吗?

http://facebook.github.io/react/docs/two-way-binding-helpers.html

你甚至可以实现自己的mixin


Man*_*anu 7

如果有人寻找功能组件示例,

import React, { useState } from "react";

export default function Exapmle() {

const [userState, setUserState] = useState({
  firstName: "",
  lastName: ""
})

const handleChange = (e)=>{
   const value = e.target.value;
   setUserState({
    ...userState,
    [e.target.name]: value
   });
}

return (
  <form>

    <label>
      First name
      <input type="text" name="firstName" value={userState.firstName}
        onChange={handleChange}
      />
    </label>

    <label>
      Last name
      <input type="text" name="lastName" value={userState.lastName}
        onChange={handleChange}
      />
    </label>

  </form>
 );
}
Run Code Online (Sandbox Code Playgroud)


ino*_*tia 6

你也可以这样做:

...
constructor() {
    super();
    this.state = { input1: 0, input2: 0 };
    this.handleChange = this.handleChange.bind(this);
}

handleChange(input, value) {
    this.setState({
        [input]: value
    })
}

render() {
    const total = this.state.input1 + this.state.input2;
    return (
        <div>
            {total}<br />
            <input type="text" onChange={e => this.handleChange('input1', e.target.value)} />
            <input type="text" onChange={e => this.handleChange('input2', e.target.value)} />
        </div>
    )
}
Run Code Online (Sandbox Code Playgroud)


Jan*_*lak 5

您可以使用一个特殊的React属性调用ref,然后onChange使用ReactgetDOMNode()函数匹配事件中的真实 DOM 节点:

handleClick: function(event) {
  if (event.target === this.refs.prev.getDOMNode()) {
    ...
  }
}

render: function() {
  ...
  <button ref="prev" onClick={this.handleClick}>Previous question</button>
  <button ref="next" onClick={this.handleClick}>Next question</button>
  ...
}
Run Code Online (Sandbox Code Playgroud)

  • @usagidon - `prev` 只是我在 `render()` 方法中设置的一个名称 (2认同)
  • 从 React v0.14 开始,你可以只做 `event.target === this.refs.prev`。https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#dom-node-refs (2认同)

归档时间:

查看次数:

89991 次

最近记录:

5 年,11 月 前