通过反应更改文本输入的焦点
Change focus of text input with react
我的目标是创建一个表单,它会在您按下 return 键时跳转到下一个输入元素,并在您进行最后一次输入时提交表单。
这是为移动设备构建的,因为在浏览器中没有使用 'next' 按钮代替 'go keyboard' 按钮的选项(有关此的更多信息,请参阅 this answer ).
为了更好地形象化,这是一张图片:
我也写了一些代码,但这里的重点是我无法在正确的位置捕获事件,所以在 return 之后或当我阻止事件,在我点击 return 2 次后焦点改变了。
看这里的例子:https://codepen.io/ofhouse/pen/Rgwzxy(我也粘贴了下面的代码)
class TextInput extends React.Component {
constructor(props) {
super(props);
this._onKeyPress = this._onKeyPress.bind(this);
}
componentDidMount() {
if (this.props.focus) {
this.textInput.focus();
}
}
componentDidUpdate(nextProps) {
if (nextProps.focus) {
this.textInput.focus();
}
}
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
}
}
render() {
return (
<div>
<input
type="text"
onKeyPress={this._onKeyPress}
ref={input => {
this.textInput = input;
}}
/>
</div>
);
}
}
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
currentElement: 0,
};
}
_submitForm(e) {
// If I remove this preventDefault it works, but also the form is submitted --> SiteReload
e.preventDefault();
}
_changeFocus(nextElement) {
return e => {
this.setState({
currentElement: nextElement,
});
};
}
render() {
const { currentElement } = this.state;
return (
<form>
<h1>React input focus</h1>
<TextInput focus={currentElement === 0} onSubmit={this._changeFocus(1)} />
<TextInput focus={currentElement === 1} onSubmit={this._changeFocus(0)} />
<div>
<button type="submit" onClick={this._submitForm}>Submit</button>
</div>
</form>
);
}
}
ReactDOM.render(<Application />, document.getElementById('app'));
我不认为你使用的是最好的方法,让我解释一下。输入的焦点由本机 DOM 元素的 focus
方法完成。要知道根据哪个输入具有当前焦点来关注哪个输入是必须在这些输入的容器中实现的逻辑,在您的情况下是 Application
组件。
我对您的代码进行了一些重大更改,现在它可以正常工作了:CodePen
让我解释一下:
首先,当按下的键为 'Enter'
时,我们阻止提交输入的 keyPressed
事件,以防止表单 submit
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
e.preventDefault();
}
}
我们既不需要 componenDidMount
也不需要 componentDidUpdate
TextInput
我们只需要一个 focus
方法:
focus() {
this.textInput.focus();
}
大部分更改是在 Application
组件中进行的。首先,我们不需要状态,我们真正需要的是将输入放在一个数组中,这样我们就可以对它们调用 focus
。
constructor(props) {
super(props);
this.inputs = [];
}
要改变焦点,我们只需要输入的索引来调用TextInput
组件的focus
方法:
_changeFocus(index) {
return e => {
this.inputs[index].focus();
};
}
然后我们需要一种方法将输入添加到 this.inputs
,ref
属性 将是理想的,我创建了方法 _addInput
作为助手为此:
_addInput(index) {
return input => {
this.inputs[index] = input;
};
}
最后,在渲染 TextInput
时,您需要将它们 _addInput
传递给 ref
和 _changeFocus
传递给 onSubmit
,以及它们各自的索引:
<TextInput ref={this._addInput(0)} onSubmit={this._changeFocus(1)} />
<TextInput ref={this._addInput(1)} onSubmit={this._changeFocus(0)} />
在第二个 TextInput
中,我将焦点转移到第一个,但也许提交表单会更有用。
我的目标是创建一个表单,它会在您按下 return 键时跳转到下一个输入元素,并在您进行最后一次输入时提交表单。
这是为移动设备构建的,因为在浏览器中没有使用 'next' 按钮代替 'go keyboard' 按钮的选项(有关此的更多信息,请参阅 this answer ).
为了更好地形象化,这是一张图片:
我也写了一些代码,但这里的重点是我无法在正确的位置捕获事件,所以在 return 之后或当我阻止事件,在我点击 return 2 次后焦点改变了。
看这里的例子:https://codepen.io/ofhouse/pen/Rgwzxy(我也粘贴了下面的代码)
class TextInput extends React.Component {
constructor(props) {
super(props);
this._onKeyPress = this._onKeyPress.bind(this);
}
componentDidMount() {
if (this.props.focus) {
this.textInput.focus();
}
}
componentDidUpdate(nextProps) {
if (nextProps.focus) {
this.textInput.focus();
}
}
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
}
}
render() {
return (
<div>
<input
type="text"
onKeyPress={this._onKeyPress}
ref={input => {
this.textInput = input;
}}
/>
</div>
);
}
}
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
currentElement: 0,
};
}
_submitForm(e) {
// If I remove this preventDefault it works, but also the form is submitted --> SiteReload
e.preventDefault();
}
_changeFocus(nextElement) {
return e => {
this.setState({
currentElement: nextElement,
});
};
}
render() {
const { currentElement } = this.state;
return (
<form>
<h1>React input focus</h1>
<TextInput focus={currentElement === 0} onSubmit={this._changeFocus(1)} />
<TextInput focus={currentElement === 1} onSubmit={this._changeFocus(0)} />
<div>
<button type="submit" onClick={this._submitForm}>Submit</button>
</div>
</form>
);
}
}
ReactDOM.render(<Application />, document.getElementById('app'));
我不认为你使用的是最好的方法,让我解释一下。输入的焦点由本机 DOM 元素的 focus
方法完成。要知道根据哪个输入具有当前焦点来关注哪个输入是必须在这些输入的容器中实现的逻辑,在您的情况下是 Application
组件。
我对您的代码进行了一些重大更改,现在它可以正常工作了:CodePen
让我解释一下:
首先,当按下的键为 'Enter'
时,我们阻止提交输入的 keyPressed
事件,以防止表单 submit
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
e.preventDefault();
}
}
我们既不需要 componenDidMount
也不需要 componentDidUpdate
TextInput
我们只需要一个 focus
方法:
focus() {
this.textInput.focus();
}
大部分更改是在 Application
组件中进行的。首先,我们不需要状态,我们真正需要的是将输入放在一个数组中,这样我们就可以对它们调用 focus
。
constructor(props) {
super(props);
this.inputs = [];
}
要改变焦点,我们只需要输入的索引来调用TextInput
组件的focus
方法:
_changeFocus(index) {
return e => {
this.inputs[index].focus();
};
}
然后我们需要一种方法将输入添加到 this.inputs
,ref
属性 将是理想的,我创建了方法 _addInput
作为助手为此:
_addInput(index) {
return input => {
this.inputs[index] = input;
};
}
最后,在渲染 TextInput
时,您需要将它们 _addInput
传递给 ref
和 _changeFocus
传递给 onSubmit
,以及它们各自的索引:
<TextInput ref={this._addInput(0)} onSubmit={this._changeFocus(1)} />
<TextInput ref={this._addInput(1)} onSubmit={this._changeFocus(0)} />
在第二个 TextInput
中,我将焦点转移到第一个,但也许提交表单会更有用。