使用React更改textarea中的光标位置

时间:2016-07-14 23:54:52

标签: javascript jquery reactjs

我在React有一个textarea,我想变成一个"记事本"。这意味着我想要"标签"缩进的关键而不是无焦点。我查看了this answer,但我无法与React合作。这是我的代码:

handleKeyDown(event) {
    if (event.keyCode === 9) { // tab was pressed
        event.preventDefault();
        var val = this.state.scriptString,
            start = event.target.selectionStart,
            end = event.target.selectionEnd;

        this.setState({"scriptString": val.substring(0, start) + '\t' + val.substring(end)});
        // This line doesn't work. The caret position is always at the end of the line
        this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1;
    }
}
onScriptChange(event) {
   this.setState({scriptString: event.target.value});
}
render() {
    return (
        <textarea rows="30" cols="100" 
                  ref="input"
                  onKeyDown={this.handleKeyDown.bind(this)}
                  onChange={this.onScriptChange.bind(this)} 
                  value={this.state.scriptString}/>
    )
}

当我运行此代码时,即使我按下&#34;标签&#34;键盘中间的键,我的光标总是出现在字符串的末尾。任何人都知道如何正确设置光标位置?

4 个答案:

答案 0 :(得分:23)

在状态更新后,您必须更改光标位置setState()不会立即变异this.state

为了做到这一点,你必须在函数中包装this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1;并将其作为第二个参数传递给setState(回调)。

handleKeyDown(event) {
      if (event.keyCode === 9) { // tab was pressed
          event.preventDefault();
          var val = this.state.scriptString,
          start = event.target.selectionStart,
          end = event.target.selectionEnd;
          this.setState(
              {
                  "scriptString": val.substring(0, start) + '\t' + val.substring(end)
              },
              () => {
                  this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1
              });
      }
 }

jsfiddle

答案 1 :(得分:4)

对于任何寻求快速React Hooks(16.8+)光标位置示例的人:

import React { useRef } from 'react';

export default () => {

  const textareaRef = useRef();
  const cursorPosition = 0;

  return <textarea
    ref={textareaRef}
    onBlur={() => textareaRef.current.setSelectionRange(cursorPosition, cursorPosition)}
  />

}

在此示例中,当输入不再聚焦时,使用setSelectionRange将光标位置设置为cursorPosition的值。

答案 2 :(得分:0)

这是一个挂钩风格的体系结构中的解决方案。我的建议是在插入标签时立即更改文本区域valueselectionStart

import React, { useRef } from "react"

const CodeTextArea = ({ onChange, value, error }) => {
  const textArea = useRef()
  return (
      <textarea
        ref={textArea}
        onKeyDown={e => {
          if (e.key === "Tab") {
            e.preventDefault()

            const { selectionStart, selectionEnd } = e.target

            const newValue =
              value.substring(0, selectionStart) +
              "  " +
              value.substring(selectionEnd)

            onChange(newValue)
            if (textArea.current) {
              textArea.current.value = newValue
              textArea.current.selectionStart = textArea.current.selectionEnd =
                selectionStart + 2
            }
          }
        }}
        onChange={e => onChange(e.target.value)}
        value={value}
      />
  )
}

答案 3 :(得分:0)

@Configuration public class XsltConfiguration { @Bean @Qualifier("XslA") XsltExecutable getXsltExecutableA() { XsltCompiler compiler = new Processor(true).newXsltCompiler(); //load xsl ... return compiler.compile(xslSource); } @Bean @Qualifier("XslB") XsltExecutable getXsltExecutableB() { XsltCompiler compiler = new Processor(true).newXsltCompiler(); //load xsl ... return compiler.compile(xslSource); } } 中,最佳选择是这样的:

React 15

您可以通过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.selectionStart值完全控制光标位置,而无需访问实际的DOM树。