Handsontable 数据与索引体系详解:source data、visual dataset 与 physical/visual 索引映射
Handsontable 数据与索引体系详解source data、visual dataset 与 physical/visual 索引映射【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontableHandsontable 在渲染表格时始终维护着两套数据视图你传入的源数据source data与用户当前看到的视觉数据集visual dataset并且用两套不同的行列索引分别定位它们。本文围绕 understanding-data-and-indexes 指南展开解释getData()与getSourceData()系列方法各自操作哪一套视图、排序/移动/隐藏/修剪如何改变两者关系以及如何借助toPhysicalRow()/toVisualRow()等转换方法与底层的 Index Mapper 机制写出不会出错的数据读写代码。读完本文你将能准确区分物理索引与视觉索引的语义、判断任意 API 方法的输入输出使用哪一套索引、理解隐藏与修剪在数据视图层面的本质差异并掌握在批量修改数据时用batch()控制重渲染开销的正确姿势。Background网格为什么维护两套数据视图当你把一个数据集传给 Handsontable 时网格并不是直接照抄显示而是同时维护两个相关联的视图源数据source data是你传入的数据集本身保持你提供的原始顺序。通过getSourceData()及一系列相关方法取回也是你应该持久化到后端的内容。视觉数据集visual dataset是用户当前实际看到的、经过排序、移动、隐藏或修剪之后的数据。通过getData()及一系列相关方法取回。在大多数情况下两个视图的行顺序完全一致区分它们没有意义一旦某个功能为了显示目的而重排或移除了行/列getData()与getSourceData()的结果就会开始分道扬镳。从源码上看这种分离是结构性的Core实例在初始化时分别创建了行、列两个IndexMapper实例作为索引映射的底层设施见 core.tsthis.columnIndexMapper new IndexMapper()、this.rowIndexMapper new IndexMapper()并且getData()/getSourceData()走的是两条完全不同的取数通道见下文。两套视图的工作方式源数据 vs. 视觉数据一个排序示例以一个 4 行的源数据集为例按第一列排序后源数组本身并不会改变——Handsontable 将新顺序单独存储因此两种方式读取会得到不同结果// source data, as provided [ [Ford, 2018], [Audi, 2020], [BMW, 2019], [Toyota, 2021], ] hot.getSourceData(); // - the original 4 rows, in the original order hot.getData(); // - the 4 rows sorted by year: Ford, BMW, Audi, Toyota需要我当初给的数据时用getSourceData()需要用户现在看到的数据时用getData()。同样的划分也适用于单单元格变体getDataAtCell()/setDataAtCell()操作视觉数据集而getSourceDataAtCell()/setSourceDataAtCell()操作源数据。完整的方法清单可参考 Binding to dataRelated API reference。从 core.ts 的实现可以看到getData()无参调用时走datamap.getAll()带范围参数时走datamap.getRange(..., DataMap.DESTINATION_RENDERER)——这个 RENDERER 目标即表示按渲染出来的视觉顺序取数而 getSourceData() 则直接调用dataSource.getData()/dataSource.getByRange()在数据源层面按物理顺序取数不参与任何数据变换。物理索引 vs. 视觉索引Handsontable 用两种不同的行列索引来定位这两套视图物理索引physical index源数据数组中的位置。排序、移动、隐藏、修剪都不会改变它——只有插入或删除行/列才会让它变化。视觉索引visual index用户视野中的位置。只要排序、移动、隐藏或修剪改变了显示顺序视觉索引就会随之改变。方法/配置使用索引用途setDataAtCell()、getDataAtCell()、getDataAtRow()、getDataAtRowProp()视觉索引读写用户当前看到的内容setSourceDataAtCell()、getSourceDataAtCell()、getSourceDataAtRow()物理索引读写底层源数据cells配置函数物理行与列按源数据位置挂接的单元格级设置cell配置数组视觉行与列按显示位置挂接的单元格级设置在源码中getDataAtCell(row, column)的实现是datamap.get(row, datamap.colToProp(column))其 JSDoc 明确标注参数为Visual row index / Visual column index见 core.ts而getSourceDataAtCell(row, column)调用的是dataSource.getAtCell(row, column)参数为物理行索引core.ts。两者虽只有 Source 一词之差背后却是完全不同的索引语义与取数通道。四种转换方法要在两套索引之间翻译使用toPhysicalRow()、toVisualRow()、toPhysicalColumn()、toVisualColumn()。例如把视觉位置 0 的行移动到视觉位置 2 之后视觉位置物理行011220hot.toPhysicalRow(0); // - 1现在显示在第一位的是原本的第 1 行 hot.toVisualRow(0); // - 2原本第一行现在显示在第三位这组方法的完整演算示例可参考 Row movingSet a pre-defined row order 与 Column movingSet a pre-defined column order。在内部Handsontable 还维护着第三种面向 DOM 渲染的renderable可渲染索引但公共 API 方法不接受 renderable 索引——它纯粹是渲染层内部的优化设施。源码中的映射实现Index Mapper这四个转换方法在Core中只是薄封装真正做翻译的是IndexMapper。例如 core.ts 中this.toVisualRow (row) instance.rowIndexMapper.getVisualFromPhysicalIndex(row); this.toPhysicalRow (row) instance.rowIndexMapper.getPhysicalFromVisualIndex(row);而 indexMapper.ts 中的getPhysicalFromVisualIndex()直接读取notTrimmedIndexesCache缓存数组getVisualFromPhysicalIndex()读取fromPhysicalToVisualIndexesCache缓存。也就是说行与列各自的IndexMapper实例indexMapper.ts内部维护了修剪后索引与物理↔视觉两套缓存任何排序、移动、隐藏、修剪操作都会触发缓存重建例如notTrimmedIndexesCache与renderablePhysicalIndexesCache在映射变更时被重新计算见 indexMapper.ts从而保证转换方法始终返回最新的映射结果。各功能如何影响两套数据不同功能在源数据 → DOM链路上的作用点不同这决定了getData()是否还包含这些行/列行为隐藏的行/列修剪的行在getSourceData()中有有在getData()视觉数据集中有无是否推移其他行/列的视觉索引否是是否渲染到 DOM否否隐藏hiding只把行/列从渲染中移除它仍留在视觉数据集中、保留自己的视觉索引。对应的插件级细节见 Row hiding。修剪trimming把行/列从视觉数据集中彻底移除其后的每一行/列视觉索引都会前移一位。对应细节见 Row trimming。理解这一差异对钩子与选择区域处理尤其重要例如在 core.ts 中rowIndexMapper.isHidden(toPhysicalRow(row))这类判断被用来在迭代视觉行时跳过被隐藏的行而修剪过的行在getData()的结果里直接不可见。关于重渲染批量操作请用batch()Handsontable 对每一次被接受的数据变更——哪怕只改一个单元格——都会重新渲染所有可见单元格。因此当需要一次性应用大量变更时应把它们包进batch()让网格只渲染一次。从 core.ts 的实现可以看到batch()的机制进入回调前先suspendRender()suspendExecution()挂起渲染与执行回调执行完毕后统一resumeExecution()resumeRender()把多次变更合并为一次渲染与一次缓存重算。官方示例core.ts展示了在batch()内同时执行多次alter(insert_col_start, ...)、多次setDataAtCell(...)、过滤器filters.filter()与排序columnSorting.sort(...)的典型场景最终表格只重渲染一次、缓存只重算一次。Trade-offs何时操作哪一套数据操作源数据当你要持久化到后端、导出数据或需要与当前显示方式无关地处理整个数据集时使用源数据 APIgetSourceData()系列。操作视觉数据当你要响应用户当前看到或点击的内容时——例如在选区钩子或数据变更钩子内部——使用视觉数据 APIgetData()系列。这也正是 Events and hooks 中提到的根据用户交互取数的推荐姿势。另一个重要的权衡点是引用绑定Handsontable 以引用by reference而非拷贝的方式绑定你的源数据因此你完全可以直接读写传入的数组。但要避免这么做——直接写数组会绕过 hooks、validators 与索引映射导致网格的视觉数据集与数组漂移失步。正确做法见 Binding to dataUnderstand binding as a reference 一节。相关指南与 APIBinding to data —— 将数据载入网格并在数组/对象等数据结构之间做选择。Saving data —— 将变更持久化回后端。Events and hooks —— 响应数据变更包括source参数。Row hiding 与 Row trimming —— 各功能插件级细节。Row moving 与 Column moving —— 在不触碰源数组的前提下重排视觉数据集。getData()、getSourceData()、toPhysicalRow()、toVisualRow()的完整 API 参考见 core.ts 相关实现以及对应的 API 文档条目。核心结论可以浓缩为一句读写用户看到的东西用视觉索引与getData()系列读写你提供的数据用物理索引与getSourceData()系列需要跨界时用toPhysicalRow()/toVisualRow()/toPhysicalColumn()/toVisualColumn()四个转换方法。理解了这层映射关系你就能在排序、移动、隐藏、修剪任意组合的场景下写出索引正确、结果可预期的数据读写代码。【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontable创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

aiohttp 文件响应基准测试升级:按 small/large 文件大小参数化 `web.FileResponse` 性能评估

aiohttp 文件响应基准测试升级:按 small/large 文件大小参数化 `web.FileResponse` 性能评估

后端Web框架WebSocket 【免费下载链接】aiohttp Asynchronous HTTP client/server framework for asyncio and Python 项目地址: https://gitcode.com/gh_mirrors/ai/aiohttp 点击查看 免费下载 本篇技术指南围绕 aiohttp 仓库变更记录 CHANGES/12913.misc.rst 展开…

2026/9/21 2:19:13 阅读更多 →
Teleport Terraform Provider 资源开发指南:从新增资源到 legacy 迁移的完整实践

Teleport Terraform Provider 资源开发指南:从新增资源到 legacy 迁移的完整实践

网络安全认证鉴权运维后端 【免费下载链接】teleport The easiest, and most secure way to access and protect all of your infrastructure. 项目地址: https://gitcode.com/gh_mirrors/tel/teleport 点击查看 免费下载 本指南以 integrations/terraform/CONTRIB…

2026/9/21 2:19:13 阅读更多 →
Nix 源码调试指南:从带调试符号的构建到 gdb/lldb 断点实战

Nix 源码调试指南:从带调试符号的构建到 gdb/lldb 断点实战

开发工具CLI 【免费下载链接】nix Nix, the purely functional package manager 项目地址: https://gitcode.com/gh_mirrors/ni/nix 点击查看 免费下载 本篇指南面向需要深入 Nix(purely functional package manager)源码内部进行排障、内存…

2026/9/21 2:19:13 阅读更多 →

最新新闻

新手入门 blessed-contrib:10 分钟搞懂 blessed 与 contrib 的关系及组件运行机制

新手入门 blessed-contrib:10 分钟搞懂 blessed 与 contrib 的关系及组件运行机制

新手入门 blessed-contrib:10 分钟搞懂 blessed 与 contrib 的关系及组件运行机制 【免费下载链接】blessed-contrib Build terminal dashboards using ascii/ansi art and javascript 项目地址: https://gitcode.com/gh_mirrors/bl/blessed-contrib blessed…

2026/9/21 2:54:35 阅读更多 →
OneUptime 自定义代码监控器(Custom Code Monitor)完全指南:用 JavaScript 脚本实现多步 API 探测与自定义指标采集

OneUptime 自定义代码监控器(Custom Code Monitor)完全指南:用 JavaScript 脚本实现多步 API 探测与自定义指标采集

可观测性后端运维前端云原生微服务AI Agent 【免费下载链接】oneuptime Complete open-source monitoring and observability platform. 项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime 点击查看 免费下载 本篇技术指南以 OneUptime 的 Custom Code …

2026/9/21 2:54:35 阅读更多 →
使用 qStudio 连接 TDengine:免费 SQL 数据分析工具实战指南

使用 qStudio 连接 TDengine:免费 SQL 数据分析工具实战指南

数据库时序数据库物联网大数据实时分析云原生 【免费下载链接】tdengine TDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps. 项目地址: http…

2026/9/21 2:54:35 阅读更多 →
10分钟渲染你的第一个3D高斯场景:gauss-splat快速上手教程(Rasterizer+相机参数+渲染流水线)

10分钟渲染你的第一个3D高斯场景:gauss-splat快速上手教程(Rasterizer+相机参数+渲染流水线)

10分钟渲染你的第一个3D高斯场景:gauss-splat快速上手教程(Rasterizer相机参数渲染流水线) 【免费下载链接】gauss-splat 本项目是基于CANN的3D Gaussian Splatting渲染加速库,通过Ascend C算子加速核心计算,提供高性能…

2026/9/21 2:54:35 阅读更多 →
Caffeine JCache 适配器 JSR-107 一致性审计:从 TCK 盲区到全规范面覆盖的工程实践

Caffeine JCache 适配器 JSR-107 一致性审计:从 TCK 盲区到全规范面覆盖的工程实践

Caffeine JCache 适配器 JSR-107 一致性审计:从 TCK 盲区到全规范面覆盖的工程实践 【免费下载链接】caffeine A high performance caching library for Java 项目地址: https://gitcode.com/gh_mirrors/ca/caffeine JSR-107(JCache)1…

2026/9/21 2:54:35 阅读更多 →
校招岗位信息操作系统:从搜索、解码到闭环的工程化方法

校招岗位信息操作系统:从搜索、解码到闭环的工程化方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 2:53:34 阅读更多 →

日新闻

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and …

2026/9/21 0:00:01 阅读更多 →
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,…

2026/9/21 0:00:01 阅读更多 →
Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

桌面应用AI 应用插件系统 【免费下载链接】Wox A cross-platform launcher that simply works 项目地址: https://gitcode.com/gh_mirrors/wo/Wox 点击查看 免费下载 全功能插件(Full-featured Plugin)是 Wox 三类插件实现方式中能力最完整的…

2026/9/21 0:00:01 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →