在按下Enter键后调用onChange事件

to call onChange event after pressing Enter key

本文关键字:调用 onChange 事件 Enter      更新时间:2023-09-26

我是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
});

根据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组件

下面是使用React的代码。做同样事情的组件

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

这是jsfield

更新2:使用功能组件

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

可以直接在输入字段上使用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()
                }
              }}
/>

在表单控件(输入)中按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>

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

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

更多信息在这里。

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

您可以使用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>

我更喜欢onKeyUp,因为它只在键被释放时触发。另一方面,如果用户出于某种原因按下并持有该键,则onKeyDown将触发多次。例如,在听"按"音时,Enter键发出网络请求,您不希望多次触发它,因为它可能会很昂贵。

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

同时,远离keyCode,因为它将来会被弃用。

React用户,这里有一个完整的答案

React version 16.4.2

您要么想在每次击键时更新,要么只在提交时获取值。将关键事件添加到组件中是有效的,但也有官方文档中推荐的替代方法。

受控组件与非受控组件

From the Docs - Forms and Controlled components:

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

我们可以通过使React状态成为"单一源"来组合两者的真相"。然后,呈现表单的React组件也会进行控制在随后的用户输入中,表单中会发生什么。输入表单元素,其值以这种方式由React控制,称为"控制组件"。

如果你使用一个受控组件,你将不得不在每次改变值时保持状态更新。为此,您需要将事件处理程序绑定到组件。在文档的示例中,通常是onChange事件。

的例子:

1)在构造函数中绑定事件处理器(值保存在状态中)

constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
}
2)创建handler函数
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函数将始终被触发,以更新和保持适当的状态。状态将始终具有更新的值,并且在提交表单时,该值将从状态中获取。如果您的表单很长,这可能是一个缺点,因为您将不得不为每个组件创建一个函数,或者编写一个简单的函数来处理每个组件的值更改。

控制

从文档-未控制组件

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

写入非受控组件,而不是写入事件处理每个状态更新,您可以使用一个ref来获取表单值

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

的例子:

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

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')
);

您也可以编写像这样的小包装器函数

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)}/>

防止输入时提交表单的示例,在我的例子中是一个google maps位置自动完成输入

<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()
    }
  }}
/>

这个比所有其他的解决方案都好:

<!-- html -->
<input type="text" onkeydown='handleKeyPress(this)'>

// js
function handleKeyPress(e)
{
    if (event.key === 'Enter') 
    {
        // call your method here
    }
}

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

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>
    )
  }      
}
const [value, setValue] = useState("");
const handleOnChange = (e) => {
    setValue(e.target.value);
};
const handleSubmit = (e) => {
    e.preventDefault();
    addTodoItem(value.trim());
    setValue("");
};
return (
    <form onSubmit={handleSubmit}>
        <input value={value} onChange={handleOnChange}></input>
    </form>
);
//You can use onkeyup directly on input field
    const inputField = document.querySelector("input");
        inputField.addEventListener("keyup", e => {
         
            if (e.key == "Enter") {
                 console.log("hello");
            }
        });