我编写了一个自定义内容可编辑组件,如下所示
export default class TextEditor extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
onChange = (e) => {
let value = e.target.innerHTML;
this.props.onChange(value);
}
render() {
const { enabled , onChange , style, className, value } = this.props;
return (
<div>
<div contentEditable={enabled}
dangerouslySetInnerHTML={{ __html: value }}
ref={this.ref}
onInput={this.onChange}
style={{
...style,
height: '80px',
overflow: 'auto',
cursor: enabled ? 'text' : 'inherit',
}}
className={`form-control form-control-sm ${className}`}
placeholder="Optional Notes..."
/>
</div>
)
}
}
无论我在可编辑内容上键入什么内容,光标都会移动到可编辑区域的开头。 这是因为this.props.onChange(value);更新外部值并重新渲染。如何防止在重新渲染时重置光标?
答案 0 :(得分:1)
您将需要componentDidMount
和shouldComponentUpdate
的组合,如下所示:
class TextEditor extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
this.onChange = this.onChange.bind(this);
}
onChange(){
var html = this.ref.current.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({value: html});
}
this.lastHtml = html;
}
shouldComponentUpdate(nextProps){
return nextProps.value !== this.ref.current.innerHTML;
}
componentDidUpdate() {
if ( this.props.value !== this.ref.current.innerHTML ) {
this.ref.current.innerHTML = this.props.value;
}
}
render() {
const { enabled , style, className, value } = this.props;
return (
<div>
<div contentEditable={enabled}
dangerouslySetInnerHTML={{ __html: value }}
ref={this.ref}
onInput={this.onChange}
onBlur={this.onChange}
className="editable"
placeholder="Optional Notes..."
/>
</div>
)
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.state = {value: ""};
}
onChange({value}) {
this.setState({value})
}
render(){
return (
<TextEditor enabled={true} onChange={this.onChange} value={this.state.value}/ >
)
}
}
ReactDOM.render( <App/> , document.getElementById('app'));
.editable {
width: 100%;
height: 100px;
border: 1px solid black;
}
<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="app"></div>