About setting the textarea cursor position?

1. The requirements are as follows

has a textarea tag. You need to get the position of the cursor and insert the specified content according to the position of the cursor.

bind the value of textarea bidirectionally through v-model, and bind the input event by textarea. When you enter textarea, you can trigger the input event, but you cannot trigger the input event by representing the value value through the code, so I added the value value to listen in the watch, so that as soon as the value value changes, the method in the watch can be triggered.

2. Question

as shown above, the cursor position is at the end and does not change the cursor position

the code is as follows:

watch:{
    value:function(val, oldval){
        this.$refs.input.focus();
        this.html = Marked(this.value);
        console.log(this.$refs.input.selectionStart);  // console
        this.$refs.input.focus();
        // this.startthis.end
        this.$refs.input.selectionStart = this.start + 2;        
        this.$refs.input.selectionEnd = this.end + 2;
        console.log(this.$refs.input.selectionStart); // console  2
    }
},

actually changes the value of this.$refs.input.selectionStart, but the cursor position hasn"t changed visually. Why?
in addition, I tried to set the cursor position in a pure html file, which is for the problem, is it the Vue problem? Or is it my code logic problem?

Feb.28,2021

adding a setTimeout is OK, but there is a problem. The cursor will flash at the last time, and then return to the position you set immediately.
you can first blur, then get the location, and then focus.
reference

tabDelete (e) { //  tab 
  const TABKEY = 9;
  if (e.keyCode === TABKEY) {
    let pos = this.$refs['mTextarea'].selectionStart
    if (pos >= 0) {
      this.input = this.input.splice(pos, '    ')
      this.$refs['mTextarea'].blur()
      setTimeout(() => {
        this.$refs['mTextarea'].selectionStart = pos + 4
        this.$refs['mTextarea'].selectionEnd = pos + 4
        this.$refs['mTextarea'].focus()
      })
    }
    if(e.preventDefault) {
      e.preventDefault()
    }
  }
}

you can try to execute the function that sets the cursor in this.$nextTick (), or set a settimeout


I also encounter the same problem. If you set it, the console comes out in the right position, but the cursor is always at the back. I don't know how you solved it


.

solution when using React

    onKeyDown = (e) => {
        const { text } = this.state;
        console.log(e.key);
        if (e.key === 'Tab') {
            const start = e.target.selectionStart;
            const _text = text.slice(0, start) + '    ' + text.slice(start);
            e.preventDefault();
            e.target.blur();
            this.setState({
                text: _text
            });
            const target = e.target;
            setTimeout(function () {
                target.focus();
                target.selectionStart = start + 4;
                target.selectionEnd = start + 4;
            })
        }
    }
Menu