在 Safari 或 Firefox 中的内容可编辑区域中输入文本时,每次按键时插入符号都会移至开头。这似乎只在 React 重新/渲染组件时才会发生。
Chrome 运行得很好。没有测试过IE。
一个示例,其中
|
是插入符号并输入 Hello
:
|
|H
|eH
|leH
|lleH
|olleH
这是我的组件的简化版本:
import React, { Component } from 'react';
class ContentEditable extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
};
}
createMarkup() {
return { __html: this.state.value };
}
handleInput(event) {
this.setState({
value: event.target.innerText
});
}
isValid() {
let bestLength = 3;
return this.state.value.length > bestLength;
}
render() {
let className = '';
if (this.isValid()) {
className = 'is-valid';
}
return (
<span
contentEditable="true"
onInput={ this.handleInput.bind(this) }
className={ className }
dangerouslySetInnerHTML={ this.createMarkup() }
>
</span>
);
}
}
ContentEditable.propTypes = {
value: React.PropTypes.string.isRequired
};
export default ContentEditable;
有人遇到过这个吗?
您可以通过向 HTML 标记添加处理程序来实现
contenteditable
。
问题是每次重新渲染内容时,光标的位置都会重置。当setState
的内容被编辑时,您会触发span
,从而重置光标位置。
您可以存储对
span
标签的引用并更新其值,而不是触发状态更改。
A
ref
可以被存储,这将在范围中注入值。
class ContentEditable extends Component {
constructor(props) {
super(props);
this.spanRef = React.createRef();
this.val = props.value;
}
handleInput(event) {
const { innerText } = event.target;
if (this.val !== innerText) {
this.spanRef.innerText = innerText;
this.val = innerText;
}
}
render() {
return (
<span
contentEditable="true"
className={"is-valid"}
onInput={this.handleInput.bind(this)}
ref={this.spanRef}
suppressContentEditableWarning={true}
>
{this.val}
</span>
);
}
}
我知道我参加聚会迟到了,但这可能对其他人有帮助,或者您也可以在其他问题上找到类似类型的解决方案。
当您直接更新或打印节点中的值时,Html 适用于节点概念,因为反应重新渲染它会重置光标位置以开始。您必须使用 HTML Web API 以编程方式将值传递给元素,这里是修改后的代码。
class ContentEditable extends Component {
constructor(props) {
super(props);
this.spanRef = React.createRef();
this.val = props.value;
}
componentDidUpdate(prevState, prevPorps){
if(prevPorps?.value !== this.props.value) {
this.spanRef.innerText = this.props.value;
}
}
handleInput(event) {
const { innerText } = event.target;
if (this.val !== innerText) {
this.spanRef.innerText = innerText;
this.val = innerText;
}
}
render() {
return (
<span
contentEditable="true"
className={"is-valid"}
onInput={this.handleInput.bind(this)}
ref={this.spanRef}
suppressContentEditableWarning={true}
>
</span>
);
}
}