document.execCommand 可用但不可靠,已弃用且跨浏览器行为不一致;需全小写命令、确保焦点与选区、避免在 <pre>/<code> 中使用,并注意移动端限制。

document.execCommand 还能用,但不是“随便一调就生效”。它现在是“可用但不可靠”的状态——Chrome 120+、Firefox、Safari 都没删掉,但 MDN 已标 deprecated,且行为差异大、边界 case 多。想快速搭个带粗体/颜色/列表的编辑器原型?可以,但得踩准几条线。
command 名必须全小写,大小写敏感
比如 'Bold' 或 'BOLD' 都不会报错,但静默失败;只有 'bold'、'italic'、'insertUnorderedList' 这类全小写才有效。命令列表里混着旧 IE 风格(如 '2D-Position'),但现代浏览器只认常用那十几个,其他基本忽略。
-
'bold'、'italic'、'underline':基础格式,参数第三位传null -
'foreColor'或'backColor':第三位传十六进制色值,如'#333'或'rgb(51, 51, 51)' -
'formatBlock':第三位传字符串'<h2>'</h2>、'<p>'</p>,注意尖括号和引号都要,'h2'不行 -
'insertHTML':第三位传合法 HTML 字符串,如'<span class="note">xxx</span>',但不推荐用于结构复杂内容
执行前必须确保焦点 + 选区存在
点击按钮后没反应?大概率是链路断在第一步。execCommand 不会自动聚焦或创建选区,它只作用于当前 document 的 activeElement 和 getSelection() 结果。
- 调用前必须先
editor.focus(),尤其在 Modal、Tab 切换、或从 input 切回来之后 - 空选区(光标在文本中但没选中文字)执行
'bold'会插入<strong></strong>,执行'insertUnorderedList'会生成空<ul><li><br></li></ul></li> <li>建议加一层判断:<code>if (window.getSelection().toString().trim() === '') return
,避免意外插入空标签
contenteditable 容器不能是 <pre> 或 <code>
这两个标签默认禁用换行、样式继承和 execCommand 的大部分命令。哪怕加了 contenteditable="true",'bold' 也可能无反应,'formatBlock' 直接被忽略。
立即学习“前端免费学习笔记(深入)”;
正确做法是用 <div contenteditable="true"> 或 <p contenteditable="true"> 作为根容器。如果需要保留代码块语义,应在内部用 <code> 包裹纯文本段落,而非把整个编辑区设为 <code>。
移动端 iOS Safari 对 formatBlock 基本不支持
在 iPhone 上调用 document.execCommand('formatBlock', false, '<h2>')</h2> 极大概率静默失败,连 console.warn 都没有。这不是 bug,是 WebKit 长期未实现该命令的完整逻辑。
- 检测方式:
navigator.platform.includes('iPhone')或/iPad|iPhone|iPod/.test(navigator.userAgent) - 降级方案:对标题类操作,改用插入带 class 的
<div class="heading-h2">xxx</div>,再靠 CSS 渲染样式 - 别指望它能和桌面端输出一致——同一段操作,在 Chrome 输出
<h2><strong>xxx</strong></h2>,在 Safari 可能变成<h2 style="font-weight:bold">xxx</h2>,这是常态
真正难的不是让按钮变粗,而是让同一段用户操作,在不同设备、不同浏览器、不同 selection 范围下,产出可预测、可清理、可测试的 HTML。execCommand 的输出结构不可控,<b> / <strong> / style="font-weight" 混杂,<font> 标签还在某些场景冒头——这些细节在开发时看不见,上线后却要花三倍时间修。


















