【问题标题】:Problems when updating state in React在 React 中更新状态时的问题
【发布时间】:2017-11-20 18:07:46
【问题描述】:

请查看我已说明问题的 js fiddle

这是我的 js 小提琴: https://jsfiddle.net/jajabya/fb93f7b0/

我的目标是获得一个 input 标记,其中特殊词(如日期或用户名可以通过包裹在 span 标记中突出显示)

div 一定有问题,因为当我使用输入字段时,一切正常。

我的问题是我无法让插入符号出现在正确的位置 每次状态更新时onInput

  onInput(event) {
    this.setState({
        html: event.target.innerText.toUpperCase()  
    });

  }

插入符号回滚到开头

【问题讨论】:

  • 只是一个简单的问题,为什么要在 div 元素中这样做?
  • 你为什么使用div而不是input标签?
  • 因为在input 标签中我不能有其他html标签。我希望将特殊单词包含在带有class 属性的span 标记中。
  • 但是你可以将input标签和其他标签包裹在div
  • 我不太了解你。我的想法是,如果用户在此字段中写下“我想今天去那里”,那么“今天”这个词就会被突出显示。如果您可以为我提供一个示例或至少提示如何实现这一点,我将不胜感激@MikhailKatrin

标签: javascript reactjs state caret


【解决方案1】:

我的想法是将当前插入符号位置保存在状态中,并通过 componentDidUpdate() 中的 ref 将其设置回来(因为 ref 不会重新渲染组件)。

注意:这是一个原型想法,我从未经过实战测试,因此请谨慎使用。

插入符号位置代码取自以下答案:

  1. Code for getting the caret position

  2. Code for setting caret position

class Editable extends React.Component {
  componentDidUpdate(prev) {
    const { position } = this.props;
  
    if(position !== prev.position && this.ce.childNodes.length) {
      const range = document.createRange();
      const sel = window.getSelection();
      range.setStart(this.ce.childNodes[0], position);
      range.collapse(true);
      sel.removeAllRanges();
      sel.addRange(range);
    }
  }
  
  render() {
    return (
      <div
        contentEditable
        className={this.props.className}
        onInput={this.props.onInput}
        ref={ce => this.ce = ce}
        suppressContentEditableWarning>
        {this.props.html}
      </div>
    );
  }
}

class App extends React.Component {
  state = {
    html: 'Text',
    caret: 0
  };

  handleInput = (event) => this.setState({
    html: event.target.innerText.toUpperCase(),
    position: window.getSelection().getRangeAt(0).startOffset
  });
  
  render() {
    return (
     <Editable
        {...this.state}
        className="Editable"
        onInput={this.handleInput} />
    );
  }
}

ReactDOM.render(
  <App />,
  demo
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="demo"></div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多