如何通过 keydown 事件在插入符上插入元素?

how can i insert element on caret by the keydown event?

这个功能是行不通的,但是如果我在devtools中设置断点,它会成功,为什么?好奇怪……

function insertHtmlAtCursor() {
  var range=window.getSelection().getRangeAt(0);
  var node = range.createContextualFragment("<div>this is not show</div>");
  range.insertNode(node);
}

但如果我将代码更改为此,它总是 运行 以正确的方式。

  var node = document.createTextNode('this is ok.'); 

我在 macOS 中使用 chrome,这里是演示:

editor.onkeydown=editinput;
function editinput(e) {
  if(e.isComposing||e.keyCode===229) {
    return;
  }
  if(e.keyCode==32) {//space
  var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
  }
}
<div id="editor" contenteditable="true" class="knowleadge" tabIndex="1">
</div>

这是demo,当我输入space时,它不会插入片段,但是当我在chrome中调试时,它会插入片段。

现在感谢@Dekel,我知道 keyup 替换 keydown 是一个解决方案, 但是因为我需要处理tab,而keyup并不能真正捕捉到tab键,所以我需要处理keydown中的代码,我该怎么办?

我发现 settimeout 可以解决这些问题,但是还有其他解决方案吗?这是设置的超时时间:

if(e.keyCode==32) {//space
    setTimeout(dealpace,0);
    e.stopPropagation(); 
    e.preventDefault();  
}
function dealpace() {
    var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
}

感谢@Dekel,settimeout 不是关键,关键是e.preventDefault();就像@Dekel 说的那样,keydown 插入文本,但是 keyup 将文本替换为 space。所以我们需要 e.preventDefault(); 像这样:

 if(e.keyCode==32) {//space
    dealpace();
    e.stopPropagation(); 
    e.preventDefault();  
    }
 function dealpace() {
    var range=window.getSelection().getRangeAt(0);
    var node=range.createContextualFragment('ttttttttttt');
    range.insertNode(node);
 } 

看起来两者都工作得很好:

function insertHtmlAtCursor1() {
  var range=window.getSelection().getRangeAt(0);
  var node = range.createContextualFragment("<div>this is not show</div>");
  range.insertNode(node);
}
function insertHtmlAtCursor2() {
  var range=window.getSelection().getRangeAt(0);
  var node = document.createTextNode('this is ok.'); 
  range.insertNode(node);
}
.container {
  border: 1px solid black;
  background: #fefefe;
}
<div class="container">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>

<button onClick="insertHtmlAtCursor1()">Function 1</button>
<button onClick="insertHtmlAtCursor2()">Function 2</button>

你确定你用对了吗?
究竟是什么问题?