【问题标题】:to call onChange event after pressing Enter key按下 Enter 键后调用 onChange 事件
【发布时间】:2015-09-25 03:44:24
【问题描述】:

我是 Bootstrap 的新手,遇到了这个问题。我有一个输入字段,只要我输入一个数字,就会调用来自onChange 的函数,但我希望在输入整数后按下“Enter”时调用它。验证函数也存在同样的问题 - 它调用得太快了。

var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
  //bsStyle: this.validationInputFactor(),
  placeholder: this.initialFactor,
  className: "input-block-level",
  onChange: this.handleInput,
  block: true,
  addonBefore: '%',
  ref:'input',
  hasFeedback: true
});

【问题讨论】:

    标签: javascript twitter-bootstrap reactjs


    【解决方案1】:

    根据React Doc,您可以收听键盘事件,例如onKeyPressonKeyUp,而不是onChange

    var Input = React.createClass({
      render: function () {
        return <input type="text" onKeyDown={this._handleKeyDown} />;
      },
      _handleKeyDown: function(e) {
        if (e.key === 'Enter') {
          console.log('do validate');
        }
      }
    });
    

    更新:使用 React.Component

    这是使用 React.Component 做同样事情的代码

    class Input extends React.Component {
      _handleKeyDown = (e) => {
        if (e.key === 'Enter') {
          console.log('do validate');
        }
      }
    
      render() {
        return <input type="text" onKeyDown={this._handleKeyDown} />
      }
    }
    

    这里是jsfiddle

    更新 2:使用功能组件

    const Input = () => {
      const handleKeyDown = (event) => {
        if (event.key === 'Enter') {
          console.log('do validate')
        }
      }
    
      return <input type="text" onKeyDown={handleKeyDown} />
    }
    

    【讨论】:

    • 并且您还想将验证过程绑定到onBlur 事件。
    • 参考输入文本以更紧凑的方式使用相同的解决方案:&lt;input ref='reference' onKeyPress={(e) =&gt; {(e.key === 'Enter' ? doSomething(this.refs.reference.value) : null)}} /&gt;
    • @musemind 实际上,您不需要使用ref&lt;input onKeyPress={e =&gt; doSomething(e.target.value)} 就足够了。
    • @musemind 使用类方法而不是内联函数的要点是避免每次触发onKeyPress 时都创建一个新函数。这是一个微妙的性能改进。
    • 附加的小提琴不再起作用,请检查,无论如何都是不错的答案
    【解决方案2】:

    您可以直接在输入字段上使用 onKeyPress。 onChange 函数会在每次输入字段更改时更改状态值,并在按下 Enter 后调用函数 search()。

    <input
        type="text"
        placeholder="Search..."
        onChange={event => {this.setState({query: event.target.value})}}
        onKeyPress={event => {
                    if (event.key === 'Enter') {
                      this.search()
                    }
                  }}
    />
    

    【讨论】:

    • 这个答案对我有用,而不是上面接受的答案。
    • 如果您的表单很重,我建议您在渲染方法之外创建函数并将其作为参考传递,如onKeyPress={this.yourFunc} 否则将在每次渲染时重新创建胖箭头函数。
    • 这适用于为输入和父案例编写 onKeyPress 事件的情况。谢谢。
    • onKeyPress={event =&gt; event.key === 'Enter' &amp;&amp; this.search()}
    【解决方案3】:

    在表单控件(输入)中按 Enter 通常会在表单上触发 submit (onSubmit) 事件。考虑到您可以这样处理(如果您只有一个输入,则可以选择提交按钮):

    const { useState } = React;
    
    function App() {
      const [text, setText] = useState("");
      const [submitted, setSubmitted] = useState('');
    
      function handleChange(e) {
        setText(e.target.value);
      }
    
      function handleSubmit(e) {
        e.preventDefault();
        setSubmitted(text);
        setText("");
      }
    
      return (
        <div>
          <form onSubmit={handleSubmit}>
            <input type="text" value={text} onChange={handleChange} />
            <input type="submit" value="add" />
          </form>
          submitted: {submitted}
        </div>
      );
    }
    
    ReactDOM.render(<App/>, document.getElementById('root'));
    <script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
    <div id="root"></div>

    在以下情况下执行隐式表单提交(Enter 上的submit 事件):

    • 有一个提交按钮
    • 没有提交按钮,但只有一个输入

    更多信息here

    或者,您可以将处理程序绑定到 input 上的 blur (onBlur) 事件,该事件在焦点被移除时发生(例如,切换到下一个可以获得焦点的元素)。

    【讨论】:

    • 这比使用onKeyPress干净得多。
    • 想既然目标不同,event.target.value不可用
    • 在网络应用程序的大多数情况下,没有表单,只有输入,所以这个答案与大多数用例无关,恕我直言
    • @vsync 它可能与大多数人无关,但对一部分仍然有效——而且绝对不是错误的,我认为不值得投反对票吗?
    • @vsync 你应该有一个可访问的表单元素。就像你不应该把所有东西都变成 div 一样。
    【解决方案4】:

    您可以使用event.key

    function Input({onKeyPress}) {
      return (
        <div>
          <h2>Input</h2>
          <input type="text" onKeyPress={onKeyPress}/>
        </div>
      )
    }
    
    class Form extends React.Component {
      state = {value:""}
    
      handleKeyPress = (e) => {
        if (e.key === 'Enter') {
          this.setState({value:e.target.value})
        }
      }
    
      render() {
        return (
          <section>
            <Input onKeyPress={this.handleKeyPress}/>
            <br/>
            <output>{this.state.value}</output>
          </section>
        );
      }
    }
    
    ReactDOM.render(
      <Form />,
      document.getElementById("react")
    )
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    【讨论】:

      【解决方案5】:

      响应用户,这里是完整的答案。

      反应版本 16.4.2

      您要么想为每次击键更新,要么只在提交时获取值。向组件添加关键事件是可行的,但官方文档中推荐了其他替代方法。

      受控组件与非受控组件

      受控

      来自Docs - Forms and Controlled components

      在 HTML 中,表单元素(例如 input、textarea 和 select)通常 维护自己的状态并根据用户输入进行更新。在反应中, 可变状态通常保存在组件的 state 属性中, 并且仅使用 setState() 更新。

      我们可以通过使 React 状态成为“单一来源”来将两者结合起来 真理”。然后渲染表单的 React 组件也控制 在随后的用户输入中,该表单会发生什么。输入表单 以这种方式由 React 控制值的元素称为 a “受控组件”。

      如果您使用受控组件,则每次更改值时都必须更新状态。为此,您将事件处理程序绑定到组件。在文档的示例中,通常是 onChange 事件。

      例子:

      1) 在构造函数中绑定事件处理程序(值保持状态)

      constructor(props) {
          super(props);
          this.state = {value: ''};
      
          this.handleChange = this.handleChange.bind(this);
      }
      

      2) 创建处理函数

      handleChange(event) {
          this.setState({value: event.target.value});
      }
      

      3) 创建表单提交函数(取值来自状态)

      handleSubmit(event) {
          alert('A name was submitted: ' + this.state.value);
          event.preventDefault();
      }
      

      4) 渲染

      <form onSubmit={this.handleSubmit}>
          <label>
            Name:
            <input type="text" value={this.state.value} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
      </form>
      

      如果您使用受控组件,您的handleChange 函数将始终被触发,以便更新并保持正确的状态。状态将始终具有更新的值,并且当提交表单时,该值将从状态中获取。如果您的表单很长,这可能是一个缺点,因为您必须为每个组件创建一个函数,或者编写一个简单的函数来处理每个组件的值变化。

      不受控制

      来自Docs - Uncontrolled component

      在大多数情况下,我们建议使用受控组件来实现 形式。在受控组件中,表单数据由 React 处理 零件。另一种选择是不受控制的组件,其中表单数据 由 DOM 自己处理。

      写一个不受控制的组件,而不是写一个事件 每次状态更新的处理程序,您可以使用 ref 获取表单值 来自 DOM。

      这里的主要区别是您不使用onChange 函数,而是使用表单的onSubmit 来获取值,并在必要时进行验证。

      例子:

      1) 绑定事件处理程序并在构造函数中为输入创建引用(状态中不保留值)

      constructor(props) {
          super(props);
          this.handleSubmit = this.handleSubmit.bind(this);
          this.input = React.createRef();
      }
      

      2) 创建表单提交函数(取自DOM组件)

      handleSubmit(event) {
          alert('A name was submitted: ' + this.input.current.value);
          event.preventDefault();
      }
      

      3) 渲染

      <form onSubmit={this.handleSubmit}>
          <label>
            Name:
            <input type="text" ref={this.input} />
          </label>
          <input type="submit" value="Submit" />
      </form>
      

      如果您使用不受控制的组件,则无需绑定handleChange 函数。提交表单时,该值将从 DOM 中获取,此时可能会发生必要的验证。也无需为任何输入组件创建任何处理函数。

      您的问题

      现在,针对您的问题:

      ...我希望在输入整数后按“Enter”时调用它

      如果您想实现这一点,请使用不受控制的组件。如果没有必要,不要创建 onChange 处理程序。 enter 键将提交表单,handleSubmit 函数将被触发。

      你需要做的改变:

      删除元素中的 onChange 调用

      var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
          //    bsStyle: this.validationInputFactor(),
          placeholder: this.initialFactor,
          className: "input-block-level",
          // onChange: this.handleInput,
          block: true,
          addonBefore: '%',
          ref:'input',
          hasFeedback: true
      });
      

      处理表单提交并验证您的输入。您需要从表单提交函数中的元素中获取值,然后进行验证。确保在构造函数中创建对元素的引用。

        handleSubmit(event) {
            // Get value of input field
            let value = this.input.current.value;
            event.preventDefault();
            // Validate 'value' and submit using your own api or something
        }
      

      非受控组件的使用示例:

      class NameForm extends React.Component {
        constructor(props) {
          super(props);
          // bind submit function
          this.handleSubmit = this.handleSubmit.bind(this);
          // create reference to input field
          this.input = React.createRef();
        }
      
        handleSubmit(event) {
          // Get value of input field
          let value = this.input.current.value;
          console.log('value in input field: ' + value );
          event.preventDefault();
          // Validate 'value' and submit using your own api or something
        }
      
        render() {
          return (
            <form onSubmit={this.handleSubmit}>
              <label>
                Name:
                <input type="text" ref={this.input} />
              </label>
              <input type="submit" value="Submit" />
            </form>
          );
        }
      }
      
      ReactDOM.render(
        <NameForm />,
        document.getElementById('root')
      );
      

      【讨论】:

      • 完美答案!
      【解决方案6】:

      你也可以像这样写一个小包装函数

      const onEnter = (event, callback) => event.key === 'Enter' && callback()
      

      然后在您的输入中使用它

      <input 
          type="text" 
          placeholder="Title of todo" 
          onChange={e => setName(e.target.value)}
          onKeyPress={e => onEnter(e, addItem)}/>
      

      【讨论】:

        【解决方案7】:

        阻止 Enter 在输入中提交表单的示例,在我的情况下,它是谷歌地图位置自动完成输入

        <input
          ref={addressInputRef}
          type="text"
          name="event[location]"
          className="w-full"
          defaultValue={location}
          onChange={(value) => setLocation(value)}
          onKeyDown={(e) => {
            if (e.code === "Enter") {
              e.preventDefault()
            }
          }}
        />
        

        【讨论】:

          【解决方案8】:

          下面是一个使用基于类的组件的常见用例:父组件提供回调函数,子组件渲染输入框,当用户按下回车时,我们将用户的输入传递给父组件。

          class ParentComponent extends React.Component {
            processInput(value) {
              alert('Parent got the input: '+value);
            }
          
            render() {
              return (
                <div>
                  <ChildComponent handleInput={(value) => this.processInput(value)} />
                </div>
              )
            }
          }
          
          class ChildComponent extends React.Component {
            constructor(props) {
              super(props);
              this.handleKeyDown = this.handleKeyDown.bind(this);
            }
          
            handleKeyDown(e) {
              if (e.key === 'Enter') {
                this.props.handleInput(e.target.value);
              }
            }
          
            render() {
              return (
                <div>
                  <input onKeyDown={this.handleKeyDown} />
                </div>
              )
            }      
          }
          

          【讨论】:

            【解决方案9】:

            我更喜欢onKeyUp,因为它只在释放键时触发。另一方面,onKeyDown 会在用户出于某种原因按住键时触发多次。例如,当监听“按下”Enter 键以发出网络请求时,您不希望它多次触发,因为它可能很昂贵。

            // handler could be passed as a prop
            <input type="text" onKeyUp={handleKeyPress} />
            
            handleKeyPress(e) {
            if (e.key === 'Enter') {
              // do whatever
            }
            

            }

            另外,请远离 keyCode,因为它会在一段时间内被弃用。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多