React contentEditable和光标位置

jar*_*App 6 javascript reactjs

我有简单的组件

class ContentEditable extends React.Component {
  constructor(props) {
    super(props);
    this.handleInput = this.handleInput.bind(this);
  }

  handleInput(event) {
    let html = event.target.innerHTML;
    if (this.props.onChange && html !== this.lastHtml) {
      this.props.onChange({ target: { value: html, name: this.props.name } });
      this.lastHtml = html;
    }
  }

  render() {
    return (
      <span
        contentEditable="true"
        onInput={this.handleInput}
        className={"auto " + this.props.className}
        dangerouslySetInnerHTML={{ __html: this.props.value }}
      />
    );
  }
}
export default ContentEditable;

<ContentEditable
  value={this.state.name}
  onChange={e => {
    this.setState({ name: e.target.value });
  }}
/>;
Run Code Online (Sandbox Code Playgroud)

组件有效,但我的光标始终位于第一个位置,而不是渲染文本.

我在这个论坛上测试了一些例子,但它对我不起作用.

我使用React 15.6.1并在chrome(Os X)上测试它.我有什么提示可以解决这个问题吗?

Kev*_*vin 15

解决方案useRef如下所示。

const ContentEditableWithRef = (props) => {
  const defaultValue = useRef(props.value);

  const handleInput = (event) => {
    if (props.onChange) {
      props.onChange(event.target.innerHTML);
    }
  };

  return (
    <span
      contentEditable
      onInput={handleInput}
      className="custom-textarea"
      dangerouslySetInnerHTML={{ __html: defaultValue.current }}
    />
  );
};
Run Code Online (Sandbox Code Playgroud)

完整的codesandbox可以在这里找到,用它来看看它是如何工作的!

代码沙箱示例包含两个组件

  • 一个是ContentEditableWithRef解决 的问题useRef,这是一个不受控制的组件,并且
  • 另一个组件ContentEditable用于useState解决相同的问题。

这里useRef将保持默认值/初始值与组件渲染周期分开,因此它将保留原始值,而不会受到我们在反应组件中执行的其他类型操作的影响。

这个组件做了两件事

  1. onChange这将通过一个方法将用户输入发送到父组件
  2. prop从父组件中获取指定的默认值value,并在自定义输入框中呈现该值(使用 创建的contentEditable

  • 基于引用不会重新渲染组件,因此光标将保留 (2认同)