document.execCommand("bold") 已废弃,因Chrome 97+、Firefox 89+标记为deprecated,Safari早不推荐;行为不稳定(嵌套span中多层包裹、无法撤回、不兼容Shadow DOM),返回值恒为true且无语义区分(强制<b>而非<strong>),不感知父容器类型易破坏DOM结构,且无法精准处理部分选中。

直接用 document.execCommand() 实现粗体、斜体按钮是可行的,但已废弃,现代项目应改用 Selection + Range API 或基于 contenteditable 的状态检测 + DOM 操作
为什么不能继续用 document.execCommand("bold")
这个 API 在 Chrome 97+、Firefox 89+ 中已被标记为 deprecated,Safari 早已不推荐;调用后行为不稳定(比如在嵌套 <span> 中可能包裹多层、无法撤回格式、不兼容 Shadow DOM);返回值始终为 true,无法判断是否真正生效。
- 它不区分语义意图:
execCommand("bold")总是插入<b>,而你可能想用<strong> - 对已选中文本的父容器类型无感知,容易把
<strong>套在<p>外面,破坏结构 - 无法处理部分选中(如只选中一个单词),常导致整行被包裹
如何用 Selection 和 Range 实现可预测的加粗
核心思路:获取当前选区 → 判断是否已存在 <strong> 父级 → 若有则移除,否则包裹。不依赖浏览器内置格式化逻辑。
- 用
window.getSelection()获取选区,再用getRangeAt(0)提取首个 Range - 用
range.commonAncestorContainer找到最近公共祖先节点,避免误判 - 用
range.intersectsNode(node)配合遍历,精准识别是否已有<strong>包裹该段文本 - 包裹时用
range.surroundContents(newNode),但需先确保 range 不跨元素边界(否则报错),必要时用range.cloneContents()+ 手动重建
简例:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
立即学习“前端免费学习笔记(深入)”;
function toggleBold() {
const sel = window.getSelection();
if (!sel.rangeCount) return;
const range = sel.getRangeAt(0);
const parent = range.commonAncestorContainer;
const isBold = parent.closest('strong') ||
Array.from(range.cloneContents().querySelectorAll('*'))
.some(el => el.tagName === 'STRONG');
if (isBold) {
// 解包逻辑:提取文本节点,替换父 strong
const frag = document.createDocumentFragment();
while (range.firstChild) frag.appendChild(range.firstChild);
range.insertNode(frag);
} else {
const strong = document.createElement('strong');
range.surroundContents(strong);
}
}
斜体按钮要特别注意 <i> 和 <em> 的语义选择
很多编辑器默认用 <i>,但若你的内容面向可访问性或 SEO,<em> 更合适——屏幕阅读器会改变语调,且语义明确表示“强调”。
- 不要硬编码
document.execCommand("italic"),它固定输出<i> - 在 toggle 函数里统一用
document.createElement('em'),和加粗保持一致的设计原则 - 如果后端要求纯视觉样式(如邮件模板),才考虑降级为
<i>,但需显式配置开关,而非默认 - 注意:CSS 中
font-style: italic对<em>是默认生效的,无需额外样式
按钮状态同步必须手动检测,没有自动回调
浏览器不会通知你“当前光标处是否在 <strong> 内”,所以工具栏按钮的激活态(active/on)必须每次聚焦或选区变化时重新计算。
- 监听
selectionchange事件,而非仅靠点击按钮时检查 - 用
document.caretPositionFromPoint(x, y)或getSelection().anchorNode向上遍历.parentElement查找strong/em - 避免用
computedStyle判断粗细(如fontWeight === "bold"),它无法区分<b>、<strong>、CSS 设置的 bold,且不反映语义 - 复杂场景(如表格单元格内、列表项中)建议缓存最近一次有效格式上下文,减少重复遍历开销
最易被忽略的一点:当用户用键盘(Tab / Shift+Tab)切换焦点,或通过 JS 插入内容后未触发 selectionchange,按钮状态就会滞后。必须在所有可能改变选区的操作后主动调用状态更新函数。


















