最近封装了一个vue编辑器组件,发现按回车键,换行后,光标定位在开头,而不是回车的地方。
为什么要封装编辑器?
因为我要模拟word的输入,并且需要标记出来输入区域。如下图:
如果使用输入框,则中括号[]标记不会随着文字走,比如内容换行的效果
换行的时候,标记是跟着内容的。
解决方案
使用Selction和Range对象来解决。
通过Selection对象获取光标所在对象,然后通过Range对象获取光标的位置,记录回车时光标的位置,等刷新后再把光标设置回去。
关键代码如下:
<span
ref="elInput"
class="word-text"
:placeholder="props.placeholder"
:class="[props.inputClass, { disable: props.disable }]"
:contenteditable="!props.disable"
@input="onInputValue"
@keypress.enter="onKeyPress"
@keyup.enter="onKeyup"
>
{{ props.value || "" }}
</span>
当按下回车键的时候记录光标位置,回车键结束时重新设置光标位置。
const onKeyPress = (e) => {
const el = e.target;
const val = e.target.innerText;
var selection = window.getSelection();
var range = selection!.getRangeAt(0);
// 回车键,记录光标位置
cursorIndex.value = range.startOffset;
};
const onKeyup = (e) => {
// 只有光标被标记了,才进行处理
if (cursorIndex.value <= 0) {
return;
}
const el = e.target;
const val = e.target.innerText;
var selection = window.getSelection();
var range = selection!.getRangeAt(0);
selection.removeAllRanges();
// 在光标移动结束后重新设置
setTimeout(() => {
// 设置光标开始位置
range.setStart(el.firstChild, Math.min(cursorIndex.value + 1, val.length));
// 添加选区
selection.addRange(range);
// 清除光标标记
cursorIndex.value = 0;
}, 0);
};
上面就是解决方案,有的人我看直接在一个keyup事件中就解决了,我试了在keyup中处理不管用。