Range对象通过document.createRange()创建,不可见且不渲染,需用selection.addRange()绑定到页面选区或调用deleteContents()等方法操作DOM。

Range 不是直接写在 HTML 里的标签,它完全由 JavaScript 控制,没有对应 HTML 属性或元素;想用 Range,必须调用 document.createRange() 创建实例,再配合 Selection 或手动设置边界点来生效。
Range 对象怎么创建和绑定到页面上
Range 本身不渲染、不可见,只是内存中的一个“区域描述”。你得先创建它,再把它塞进当前选区(Selection),或者用它操作 DOM:
-
document.createRange()是唯一入口,不能通过 HTML 属性生成 - 要让 Range 可见(比如高亮一段文字),需用
selection.addRange(range)主动添加到用户选区 - 如果只是做后台内容提取或删除,不添加到
Selection也行,直接调range.toString()或range.deleteContents() - 注意:Firefox 支持多段选区(
selection.rangeCount > 1),Chrome/Edge 通常只返回 1 个Range,别默认getRangeAt(0)就够用
selectNode 和 selectNodeContents 的区别到底在哪
这两个方法决定 Range 的起止边界落在节点的什么位置,直接影响 deleteContents() 删的是“整个元素”还是“仅内容”:
-
range.selectNode(node):起点 =node的父节点中node的插入位置,终点 = 该位置之后;结果包含<div>xxx</div>整个标签结构 -
range.selectNodeContents(node):起点 =node.firstChild的开头,终点 =node.lastChild的结尾;结果只包含xxx,不包括<div>标签本身 - 常见误用:对空
<div></div>调selectNodeContents会创建一个空 Range,deleteContents()无效果,但不会报错 - 若目标节点是文本节点(
node.nodeType === 3),只能用setStart/setEnd,selectNode会静默失败
用 setStart/setEnd 定位文字内部时容易出错的点
这对方法最灵活,但也最容易因参数错位导致 Range 为空或越界:
立即学习“前端免费学习笔记(深入)”;
- 第一个参数必须是祖先节点(通常是父元素或文本节点),不能传
document或任意非相关节点 - 第二个参数是偏移量(offset):对元素节点,是子节点索引;对文本节点,是 Unicode 码点位置(不是字节数,中文、emoji 都算 1)
-
range.setStart(textNode, 5)表示从第 5 个字符开始,但若textNode.textContent.length < 5,Range 边界会被截断为末尾,不抛异常 - 调用顺序有影响:必须先
setStart再setEnd,反过来可能让 Range 倒置(起点在终点右边),此时range.collapsed为true,后续操作无效 - 修改 DOM 后(如删了前面的节点),原 Range 的 offset 可能失效,建议操作前重新计算或用
range.detach()清理旧引用
deleteContents 后 DOM 状态为什么有时不对
deleteContents() 看似简单,但实际行为依赖 Range 边界是否跨元素、是否包含部分文本节点:
- 它删除的是 Range “覆盖的 DOM 子树”,不是“视觉上看到的文字”——如果 Range 跨越两个
<span>,且中间有空白文本节点,那些空白也会被删 - 删除后,浏览器会自动合并相邻文本节点,但不会自动移除空的父容器(比如删光了
<p>里所有内容,<p></p>还在) - 不要在循环中反复复用同一个 Range 实例做
deleteContents(),每次操作后应重新createRange()或显式range.detach() - 服务端渲染(SSR)或框架(React/Vue)环境下,直接操作 Range 可能绕过虚拟 DOM,造成视图与状态不一致,慎用
Range 的核心在于“精确控制边界”,而不是“选中高亮”。多数人卡在 setStart/setEnd 的 offset 计算和节点类型匹配上,建议先用 console.log(range.toString(), range.startContainer, range.startOffset) 实时验证边界是否符合预期。



















