JavaScript Selection.setBaseAndExtent 怎样设置带方向的文本选区
Selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset) 用两组边界点设置选区。第一组是锚点,第二组是焦点;焦点在文档顺序中位于锚点之前时,得到反向选区。要保留方向,就不能先把这两组参数按大小重新排序。
文档入口:https://developer.mozilla.org/en-US/docs/Web/API/Selection/setBaseAndExtent。下面用同一文本节点说明 API 语义,再讨论恢复选区的边界。这是既有 Web API 的用法解析,不是新的语言提案;示例按文档编写,未在本文环境执行。
用最小例子建立反向选区
在已有页面上添加一个文本容器和按钮。通过按钮触发设置,避免页面初始化时无条件抢占用户选区:
red green blue
// 在上方HTML之后运行,保证元素已存在
const text = document.getElementById("sample").firstChild;
const button = document.getElementById("select-word");
button.addEventListener("click", () => {
const selection = window.getSelection();
if (!selection || typeof selection.setBaseAndExtent !== "function") {
// 由产品提供不支持方向恢复时的提示
return;
}
// green占据[4, 9),锚点在词尾,焦点在词首
selection.setBaseAndExtent(text, 9, text, 4);
});
这里的字符串位置可由原文直接推导:red 后有一个空格,green 从偏移4开始、在偏移9之前结束。交换为 (text, 4, text, 9) 会覆盖相同文字,但锚点和焦点角色不同。不要把“选中文字相同”当成“选区状态完全相同”。
分清锚点焦点与范围起止
anchor 表达选择的基点,focus 表达另一端。Range 的 start 与 end 则按文档顺序组织,反向选择并不意味着 start 大于 end。因此,只保存 getRangeAt(0) 的起止位置,并不能完整保存锚点与焦点的角色。

方向描述的是文档边界顺序,不等同于屏幕上的左右方向。包含双向文字或复杂布局时,更不能仅凭视觉上的“向左拖动”推断 DOM 端点。本文例子限于普通文档中的单一文本节点。
按节点类型计算偏移
Text 节点的偏移按 UTF-16 代码单元计数;Element 节点的偏移按子节点位置计数。空白文本节点也属于子节点,所以 children 的长度不能直接当作 childNodes 的长度使用。跨元素选择时,每一端都必须有自己的节点和该节点内偏移。
// 示例只接受明确的Text节点,避免把元素偏移误当字符偏移
function selectTextPart(textNode, anchor, focus) {
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
throw new TypeError("需要文本节点");
}
for (const offset of [anchor, focus]) {
// 先限制输入为非负整数,再检查节点内上界
if (!Number.isInteger(offset) || offset textNode.length) {
throw new RangeError("偏移超出文本节点范围");
}
}
if (!textNode.isConnected || textNode.ownerDocument !== document) {
throw new Error("节点必须位于当前文档");
}
const selection = window.getSelection();
if (!selection || typeof selection.setBaseAndExtent !== "function") {
return false; // 将不支持情况交给调用方处理
}
selection.setBaseAndExtent(textNode, anchor, textNode, focus);
return true;
}
这段封装有意只处理当前文档内的文本节点,不是可覆盖 Shadow DOM 或所有编辑器模型的通用库。不要把后端的字节偏移直接传进来;emoji 也可能占据两个代码单元,组合字符还可能由多个代码点构成。面向用户字符的索引需要先映射到文本节点偏移。

保存方向时保留两端角色
旧写法常把范围起止当成选区全部状态。对于需要恢复用户选择方向的编辑工具,可以先保存 anchorNode、anchorOffset、focusNode、focusOffset,再在节点仍然有效时调用 setBaseAndExtent。调用会替换当前选择范围,无须为了这一次设置先 removeAllRanges。
// 只适用于DOM节点身份与文本内容都未改变的短期保存
function captureSelection() {
const s = window.getSelection();
if (!s || s.rangeCount === 0 || !s.anchorNode || !s.focusNode) return null;
return {
anchorNode: s.anchorNode, anchorOffset: s.anchorOffset,
focusNode: s.focusNode, focusOffset: s.focusOffset
};
}
// 在受控DOM更新后,应先重建有效端点,不能盲用旧节点引用
function restoreSelection(saved) {
const s = window.getSelection();
if (!saved || !s || typeof s.setBaseAndExtent !== "function") return false;
if (!saved.anchorNode.isConnected || !saved.focusNode.isConnected) return false;
try {
s.setBaseAndExtent(
saved.anchorNode, saved.anchorOffset,
saved.focusNode, saved.focusOffset
);
return s.anchorNode === saved.anchorNode &&
s.anchorOffset === saved.anchorOffset &&
s.focusNode === saved.focusNode && s.focusOffset === saved.focusOffset;
} catch (error) {
if (error.name === "IndexSizeError") return false; // 文本缩短导致偏移失效
throw error;
}
}
框架重渲染可能替换节点;即便节点没换,文本内容变化也会改变原偏移代表的位置。长期书签应使用编辑器自己的稳定位置模型,并映射回当前 DOM;单纯 JSON 序列化节点引用不能完成这件事。
处理兼容与常见边界
| 目标 | 合适方式 | 容易忽略的点 |
|---|---|---|
| 普通文档中恢复两端角色 | setBaseAndExtent | 不要先排序anchor和focus |
| 只处理文档中的覆盖范围 | Range边界 | 范围起止不完整表达选择方向 |
| 文本输入框内选区 | setSelectionRange | 使用控件value的索引 |
input 与 textarea 应使用各自的文本选择接口。例如 text 类型输入框可以调用 setSelectionRange(start, end, "backward"),并按交互需要让控件获得焦点。不要把输入框的 value 当成可直接选择的子 Text 节点。
偏移超出节点长度会自动截断吗?
不要依赖截断。setBaseAndExtent 的越界偏移会触发 IndexSizeError,封装应提前明确输入范围。
两端相同会报错吗?
同一边界点表示折叠选区,即插入位置;它不包含一段被选中的文字。
接口存在就能覆盖所有编辑器吗?
不能。普通文档、表单控件、嵌套文档和 Shadow DOM 的处理边界不同,特性检测只说明方法存在,不能替代应用自己的节点映射。
Linux systemd.timer FixedRandomDelay 怎样保持随机延迟的稳定性
- 上一篇
- Linux systemd.timer FixedRandomDelay 怎样保持随机延迟的稳定性
- 下一篇
- JavaScript Selection.containsNode 怎样判断节点是否处于选区内
-
- 文章 · 前端 | 19分钟前 |
- JavaScript HTMLSlotElement.assignedElements 怎样读取插槽分配的元素
- 488浏览 收藏
-
- 文章 · 前端 | 24分钟前 |
- JavaScript Document.importNode 怎样复制其他文档的节点树
- 266浏览 收藏
-
- 文章 · 前端 | 27分钟前 |
- JavaScript Document.adoptNode 怎样把节点移入另一个文档
- 486浏览 收藏
-
- 文章 · 前端 | 29分钟前 |
- JavaScript NodeIterator.detach 为什么不应当作释放 DOM 的方案
- 262浏览 收藏
-
- 文章 · 前端 | 29分钟前 | javascript · 前端开发 · JavaScript 前端开发 DOM遍历 TreeWalker currentNode
- JavaScript TreeWalker.currentNode 怎样从指定节点继续遍历
- 209浏览 收藏
-
- 文章 · 前端 | 32分钟前 |
- JavaScript Range.compareBoundaryPoints 怎样比较两个范围的端点
- 300浏览 收藏
-
- 文章 · 前端 | 33分钟前 | range · javascript ·
- JavaScript Range.createContextualFragment 怎样按上下文解析 HTML 片段
- 406浏览 收藏
-
- 文章 · 前端 | 35分钟前 |
- JavaScript Selection.containsNode 怎样判断节点是否处于选区内
- 214浏览 收藏
-
- 文章 · 前端 | 11小时前 | 前端开发 · CSS 滚动条 可访问性 长列表 scrollbar-width
- CSS scrollbar-width 怎样把长列表滚动条设置为窄版
- 138浏览 收藏
-
- 文章 · 前端 | 11小时前 |
- CSS overscroll-behavior 怎样阻止嵌套滚动传递
- 483浏览 收藏
-
- 文章 · 前端 | 13小时前 |
- Vite import.meta.env 怎样区分构建期和运行期变量
- 260浏览 收藏
-
- 文章 · 前端 | 13小时前 |
- URLSearchParams 怎样删除指定键的全部参数值
- 118浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 734次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 736次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 815次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 776次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 611次使用
-
- JavaScript函数定义及示例详解
- 2025-05-11 502浏览
-
- 智能体安全引领产业升级——国内AI安全产品市场深度分析
- 2026-08-21 501浏览
-
- CSS变量简化按钮悬停效果技巧
- 2026-05-31 501浏览
-
- JavaScript符号类型详解与应用
- 2026-05-31 501浏览
-
- HTML剪贴板复制粘贴怎么用
- 2026-05-26 501浏览

