高效文本编辑器核心在于精准控制编辑行为、减少DOM干扰、保障光标稳定及预留扩展接口;采用contenteditable+execCommand构建轻量骨架,异步同步选区,手动操作Range插入内容,用textContent获取纯文本,命令模式实现撤销重做。

实现高效的文本编辑器核心逻辑,关键不在堆砌功能,而在于精准控制编辑行为、减少 DOM 干扰、保障光标稳定,并为后续扩展留出清晰接口。原生 API 足够支撑一个轻量但响应迅速的编辑体验,无需立即引入大型框架。
用 contenteditable + execCommand 搭建最小可行骨架
这是最直接的起点:设置一个 contenteditable="true" 的容器,它天然支持内联格式(如 加粗、斜体)、换行、列表等基础语义,且浏览器已做大量兼容性处理。
- 避免使用
textarea或iframe(除非需要强样式隔离),前者不渲染 HTML,后者增加上下文切换开销 - 工具栏按钮通过
data-command绑定命令名,点击时调用document.execCommand(cmd, false, value),例如'bold'、'createLink' - 命令执行后,编辑器自动更新 DOM,无需手动操作节点——这是效率来源之一
光标与选区必须异步读取和精确还原
用户操作(如输入、点击按钮)后立刻调用 getSelection(),大概率拿到的是旧状态。DOM 更新和选区同步存在微任务延迟。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 监听
input或click后,用queueMicrotask延迟获取选区,确保数据准确 - 插入自定义内容(如图片、组件)时,不能依赖
execCommand('insertHTML')(已废弃且行为不一致),应手动创建Range,再用range.insertNode()或range.deleteContents()+range.insertNode() - 保存光标位置时,记录的是文本节点路径 + 字符偏移(非字符串索引),还原时需遍历文本节点重新定位,避免因 DOM 结构变化导致节点引用失效
内容获取与变更响应要轻量可控
高频监听 input 是必要的,但直接读取 innerHTML 可能触发重排,且包含冗余标签(如空 <span></span>)。
- 用
editor.textContent获取纯文本用于搜索或摘要,比解析 HTML 快得多 - 若需结构化内容,可定期(如节流 300ms)提取
innerHTML,并用简单正则清洗无意义标签(如连续<br>、空style属性) - 对 XSS 防护不靠运行时过滤,而是在提交前用
DOMPurify.sanitize()或服务端白名单清洗,前端仅做基础提示
撤销重做不用快照,用命令模式管理状态
每秒多次输入若生成 DOM 快照,内存和性能都会快速恶化。真正高效的做法是把用户行为抽象为可逆命令。
- 定义统一命令接口:
{ execute(), undo(), name, timestamp },例如「插入字符」「应用加粗」「删除段落」 - 所有编辑入口(键盘、按钮、粘贴)都走命令调度器,由它维护
undoStack和redoStack - 连续输入自动合并:1 秒内多次
insertText合为一条命令,既保持撤销粒度合理,又避免栈爆炸

















