按键事件发生后如何获取文本光标位置?

Seb*_*ner 13 javascript dom keyboard-events dom-events

我正在写一个语法荧光笔.突出显示器应在输入文本并使用箭头键导航时立即更新突出显示.

我面临的问题是,当'keypress'事件被触发时,你仍然可以获得文本光标的旧位置window.getSelection().

例:

function handleKeyEvent(evt) {
  console.log(evt.type, window.getSelection().getRangeAt(0).startOffset);
}

var div = document.querySelector("div");
div.addEventListener("keydown", handleKeyEvent);
div.addEventListener("keypress", handleKeyEvent);
div.addEventListener("input", handleKeyEvent);
div.addEventListener("keyup", handleKeyEvent);
Run Code Online (Sandbox Code Playgroud)
<div contenteditable="true">f<span class="highlight">oo</span></div>
Run Code Online (Sandbox Code Playgroud)

在示例中,将插入符号放在单词"foo"之前,然后按(向右箭头键).

在您最喜欢的DevTool的控制台中,您将看到以下内容:

keydown 0
keypress 0
keyup 1
Run Code Online (Sandbox Code Playgroud)

0除了keypress显然是旧插入位置.如果你再坚持一下,你会得到这样的东西:

keydown 0
keypress 0
keydown 1
keypress 1
keydown 1
keypress 1
keydown 2
keypress 2
keyup 2
Run Code Online (Sandbox Code Playgroud)

我想得到的是新的插入位置,就像我将其用于'keyup'或'input'.虽然'keyup'被触发得太晚了(我想在按下键时突出显示语法)并且'input'仅在实际有一些输入时触发(但不产生任何输入).

插入符号位置发生变化后是否会触发事件而不仅仅是输入?或者我是否必须计算文本光标的位置,如果是,如何计算?(我认为当文本换行并按下(向下箭头键)时,这会变得非常复杂.)

Con*_*Fan 12

您可以使用异步setTimeout处理keydown事件:

function handleKeyEvent(evt) {
    setTimeout(function () {
        console.log(evt.type, window.getSelection().getRangeAt(0).startOffset);
    }, 0);
}

var div = document.querySelector("div");
div.addEventListener("keydown", handleKeyEvent);
Run Code Online (Sandbox Code Playgroud)
<div contenteditable="true">This is some text</div>
Run Code Online (Sandbox Code Playgroud)

该方法解决了关键处理问题.在您的示例中,您还有一个span元素div,它会改变返回的位置值

window.getSelection().getRangeAt(0).startOffset
Run Code Online (Sandbox Code Playgroud)