我正在使用 React 并格式化了一个受控输入字段,当我写一些数字并在输入字段外单击时,它可以正常工作。但是,当我想编辑输入时,光标会跳到输入字段中的值的前面。这只发生在 IE 中,而不是在 Chrome 中。我已经看到对于一些程序员来说,光标会跳到值的后面。所以我认为我的光标跳到前面的原因是因为值在输入字段中向右对齐而不是向左对齐。这是一个场景:
我的第一个输入是1000 然后我想编辑成10003,结果是31000
有没有办法控制光标不应该跳转?
我正在使用 React 并格式化了一个受控输入字段,当我写一些数字并在输入字段外单击时,它可以正常工作。但是,当我想编辑输入时,光标会跳到输入字段中的值的前面。这只发生在 IE 中,而不是在 Chrome 中。我已经看到对于一些程序员来说,光标会跳到值的后面。所以我认为我的光标跳到前面的原因是因为值在输入字段中向右对齐而不是向左对齐。这是一个场景:
我的第一个输入是1000 然后我想编辑成10003,结果是31000
有没有办法控制光标不应该跳转?
根据您的问题进行猜测,您的代码很可能与此类似:
<输入 自动对焦=“自动对焦” 类型=“文本” 值={this.state.value} onChange={(e) => this.setState({value: e.target.value})} />
如果您的事件被处理onBlur
但本质上是相同的问题,这可能会在行为上有所不同。这里的行为,许多人称其为 React “错误”,实际上是预期的行为。
输入控件的值不是控件加载时的初始值,而是对 的底层value
绑定this.state
。当状态改变时,React 会重新渲染控件。
本质上,这意味着控件由 React 重新创建并由状态值填充。问题是它无法知道光标在重新创建之前的位置。
我发现解决这个问题的一种方法是在重新渲染之前记住光标位置,如下所示:
<输入 自动对焦=“自动对焦” 类型=“文本” 值={this.state.value} onChange={(e) => { this.cursor = e.target.selectionStart; this.setState({value: e.target.value}); }} onFocus={(e) => { e.target.selectionStart = this.cursor; }} />
这是我的解决方案:
import React, { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: ""
};
//get reference for input
this.nameRef = React.createRef();
//Setup cursor position for input
this.cursor;
}
componentDidUpdate() {
this._setCursorPositions();
}
_setCursorPositions = () => {
//reset the cursor position for input
this.nameRef.current.selectionStart = this.cursor;
this.nameRef.current.selectionEnd = this.cursor;
};
handleInputChange = (key, val) => {
this.setState({
[key]: val
});
};
render() {
return (
<div className="content">
<div className="form-group col-md-3">
<label htmlFor="name">Name</label>
<input
ref={this.nameRef}
type="text"
autoComplete="off"
className="form-control"
id="name"
value={this.state.name}
onChange={event => {
this.cursor = event.target.selectionStart;
this.handleInputChange("name", event.currentTarget.value);
}}
/>
</div>
</div>
);
}
}
export default App;
这是<input/>
标签的替代品。这是一个简单的功能组件,它使用钩子来保存和恢复光标位置:
import React, { useEffect, useRef, useState } from 'react';
const ControlledInput = (props) => {
const { value, onChange, ...rest } = props;
const [cursor, setCursor] = useState(null);
const ref = useRef(null);
useEffect(() => {
const input = ref.current;
if (input) input.setSelectionRange(cursor, cursor);
}, [ref, cursor, value]);
const handleChange = (e) => {
setCursor(e.target.selectionStart);
onChange && onChange(e);
};
return <input ref={ref} value={value} onChange={handleChange} {...rest} />;
};
export default ControlledInput;
这是一个简单的解决方案。为我工作。
<Input
ref={input=>input && (input.input.selectionStart=input.input.selectionEnd=this.cursor)}
value={this.state.inputtext}
onChange={(e)=>{
this.cursor = e.target.selectionStart;
this.setState({inputtext: e.target.value})
/>
解释:
我们在这里所做的是我们将光标位置保存在 onChange() 中,现在当标签由于状态值的变化而重新渲染时,引用代码被执行,并且在引用代码中我们恢复了光标位置。
我的光标总是跳到行尾。这个解决方案似乎解决了这个问题(来自 github):
import * as React from "react";
import * as ReactDOM from "react-dom";
class App extends React.Component<{}, { text: string }> {
private textarea: React.RefObject<HTMLTextAreaElement>;
constructor(props) {
super(props);
this.state = { text: "" };
this.textarea = React.createRef();
}
handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
const cursor = e.target.selectionStart;
this.setState({ text: e.target.value }, () => {
if (this.textarea.current != null)
this.textarea.current.selectionEnd = cursor;
});
}
render() {
return (
<textarea
ref={this.textarea}
value={this.state.text}
onChange={this.handleChange.bind(this)}
/>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));