将插入符号放在可满足的ReactJS组件中

时间:2014-08-01 05:12:51

标签: javascript contenteditable reactjs

我使用ReactJS将文本值呈现到contenteditable个DOM节点中。例如:

var data = [{
  value: 'Hello '
},{
  value: 'World!'
}];

var component = React.createClass({
  render: function () {
    var pieces = this.props.data.map(function (piece) {
      return (
        <span contentEditable="false">
          <span contentEditable="true">{piece.value}</span>;
        </span>
      );
    });

    return <div contentEditable="true">{pieces}</div>;
  }
});

React.renderComponent(<component data={data} />, someContainer);

导致DOM看起来像这样(出于多种原因):

<div contenteditable="true">
  <span contentEditable="false">
    <span contentEditable="true">Hello </span>;
  </span>
  <span contentEditable="false">
    <span contentEditable="true">World!</span>;
  </span>
</div>

当用户与这些可编辑跨度交互时,例如,从第二个到第一个的退格,我可以通过从第一个模型中删除最后一个字符来更新数据,但我需要以某种方式告诉React到位光标位于第一个span[contenteditable="true"]

的末尾

我的问题:

在我的.render()函数中,我有一个this.state.caretPosition属性告诉我光标的位置(这只存在于一个组件上)。 render()应该只返回一个(虚拟)DOM节点。如何告诉ReactJS将插入符号放在返回的DOM节点中的那个位置?

示例:jsbin

2 个答案:

答案 0 :(得分:6)

我能够让您的示例使用这些how-to-set-caretcursor-position-in-contenteditable-element-divselect-range-in-contenteditable-div中描述的方法。那里使用的相同方法应该适合你。您很可能需要在componentDidMount()方法中运行它。希望有所帮助。以下是对它的外观的粗略概念:

componentDidMount: function () {
    var el = document.getElementById("a3");
    var range = document.createRange();
    var sel = window.getSelection();

    range.setStart(el.childNodes[0], 1);
    range.collapse(true);
    sel.removeAllRanges();
    sel.addRange(range);
    el.childNodes[0].focus();
  },

编辑:看到你的结构是完全嵌套的,你将不得不玩一下你实际选择哪些节点来获得所需的效果。如果光标不在可编辑元素中,则需要使用focus()调用来实际显示应用的光标位置。

答案 1 :(得分:-2)

React 15.6.1中,您可以手动设置插入位置:

class CursorForm extends Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};
  }

  handleChange = event => {
    // Custom set cursor on zero text position in input text field
    event.target.selectionStart = 0 
    event.target.selectionEnd = 0

    this.setState({value: event.target.value})
  }

  render () {
    return (
      <form>
        <input type="text" value={this.state.value} onChange={this.handleChange} />
      </form>
    )  
  }

}

您可以通过event.target.selectionStartevent.target.selectionEnd值完全控制光标位置,而无需访问真正的DOM树。