反应焦点失去对可编辑内容的关注

时间:2019-05-15 08:10:24

标签: reactjs contenteditable

我编写了一个自定义内容可编辑组件,如下所示

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);更新外部值并重新渲染。如何防止在重新渲染时重置光标?

1 个答案:

答案 0 :(得分:1)

您将需要componentDidMountshouldComponentUpdate的组合,如下所示:

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>