JS实现点击工具栏时阻止textarea失焦并保留选区与光标位置
解决方案
问题根因
- 两种尝试方案失效的核心原因是事件触发顺序问题:
mousedown事件早于blur和click事件触发,点击工具栏按钮时,mousedown阶段就已经触发了textarea的失焦逻辑,后续操作已经来不及挽回 - 方法1的
blur立刻回焦逻辑会打断工具栏按钮的点击事件,导致工具栏操作无法正常执行,还会引发光标闪烁异常等兼容性问题 - 方法2仅在
click阶段阻止事件行为,此时textarea失焦、选区丢失已经发生,完全无效
最优实现方案(无需失焦,直接保留选区)
直接阻止工具栏元素的mousedown默认行为,textarea根本不会触发失焦,选区和光标位置会完全保留,是绝大多数编辑器工具栏的通用实现方案:
示例代码
HTML
<button id="toolBtn">加粗</button> <textarea id="editor" rows="5" cols="30">测试文本,可以选中一段再点按钮</textarea>
JS
const toolBtn = document.querySelector('#toolBtn'); const editor = document.querySelector('#editor'); // 核心逻辑:阻止工具栏元素mousedown默认行为,避免textarea失焦 toolBtn.addEventListener('mousedown', e => { e.preventDefault(); }); // 工具栏点击逻辑正常编写即可,此时textarea始终持有焦点,选区完全可用 toolBtn.addEventListener('click', () => { // 示例功能:给选中内容加markdown加粗标记 const start = editor.selectionStart; const end = editor.selectionEnd; const selectedText = editor.value.slice(start, end); editor.value = editor.value.slice(0, start) + `**${selectedText}**` + editor.value.slice(end); // 可选:操作完后将光标定位到加粗内容末尾 editor.selectionStart = editor.selectionEnd = end + 2; });
兼容方案(适用于工具栏需要获得焦点的场景)
如果你的工具栏控件本身需要支持焦点交互(比如工具栏内置输入框、下拉选择器等),无法阻止mousedown默认行为,可以用「提前记录选区+操作后恢复」的方案:
示例代码
const editor = document.querySelector('#editor'); const toolInput = document.querySelector('#toolInput'); // 存储选区的变量 let savedSelection = { start: 0, end: 0 }; // 每次textarea选区变化时同步存储最新位置 editor.addEventListener('selectionchange', () => { savedSelection.start = editor.selectionStart; savedSelection.end = editor.selectionEnd; }); // 定义恢复选区的方法 function restoreTextSelection() { editor.focus(); editor.selectionStart = savedSelection.start; editor.selectionEnd = savedSelection.end; } // 工具栏操作完成后调用恢复方法即可 toolInput.addEventListener('change', () => { // 你的工具栏操作逻辑 restoreTextSelection(); });
内容的提问来源于stack exchange,提问作者Weilory
相关产品推荐
相关产品推荐

