ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Univer在线表格集成实战:从选型到协同编辑

Univer在线表格集成实战:从选型到协同编辑

前阵子公司接到一个内部系统的改造需求,业务方明确要在网页里直接编辑表格,还要能多人同时协作。前后端同事对比了一圈方案,最后把目标锁定在了一个叫 Univer 的开源项目上。折腾了将近两周,从功能验证到集成落地,中间踩了不少坑,正好把这段实战经验整理出来,给最近在关注 univer 在线表格方案的朋友做个参考。

先说 Univer 是什么。它是一套开源的在线办公套件,主打电子表格能力,同时也在向文档、幻灯片方向扩展。用大白话说,就是想在网页里做一个类似 Google Sheets 或者 WPS 网页版那样的东西,可以直接拿它当基础组件来用。相比传统的表格控件,Univer 在渲染性能、公式兼容、协同编辑、二次开发等方面做了非常多针对性的设计,尤其适合把表格能力嵌入到自己业务系统里的场景。

这篇文章不会去搬官方文档,而是从选型评估时的考量、实际接入的过程、性能与协同的落地体验,以及我这边踩过的问题四个方面展开。如果你是前端工程师、全栈开发者,或者正打算在管理系统里加一个在线表格模块,下面这些内容应该能帮你少走不少弯路。

1. Univer 是什么,为什么值得关注

1.1 我为什么要留意这个项目

先说最初的需求背景。我们内部有一个数据填报和审核系统,原来的做法是让用户下载 Excel 模板,填好再上传,后台解析校验。这套流程跑了很多年,但业务方早就抱怨了:版本容易混、格式总出错、跨部门协作效率低。于是“网页里直接改表格、改完即保存”就成了一个很自然的诉求。

第一轮选型的时候,团队里提过几类方案。一类是直接用 Excel 的网页版,但和我们的系统数据打通非常麻烦,权限和 UI 也没法定制。一类是成熟商业控件,功能完整但授权费不低,而且跟开源思维有冲突。剩下就是在开源表格组件里选。那时我们重点看了 Luckysheet、Handsontable 以及 Univer。Luckysheet 本身很优秀,但项目活跃度相对下降,而且对复杂数据结构和协同编辑的原生支持不如 Univer 来得彻底。Handsontable 商业版功能强,但开源版限制较多。相比之下,Univer 的设计理念更接近“从零开始做一套现代网页端办公套件”,而不是单纯的表格填值控件,这一点很打动我。

另外一个关键因素,是 Univer 的协议友好,采用 Apache 2.0 许可。这意味着我们可以在不自研底层的前提下,放心把它集成到商业系统里,也能按需改源码。对一个需要长期维护的内部基建来说,授权条款是否干净,比一时的功能炫酷重要得多。

1.2 与传统表格方案的区别

如果你对“网页表格”的印象还停留在“用 HTML 表格渲染行列、填 input 来做编辑”的层面上,那 Univer 带来的冲击会非常大。Univer 的底层不是 DOM 表格,而是基于 Canvas 自研的渲染引擎,数据层和视图层分离。这样做最大的好处是:当数据量变大、单元格数量增多之后,页面不会因为 DOM 节点爆炸而卡死。

它也不是一个孤零零的表格组件,而是一个插件化的平台。你可以把核心库、表格插件、协同插件、UI 插件按需组合。需要公式,加公式引擎;需要导入导出,加交换插件;需要多人协作,再接协同插件。这种搭积木式的架构,让我们在集成时能保持主业务系统的代码整洁,不用为了引入表格功能而引入一堆用不到的东西。

还有一个很细节的点:Univer 对中文场景的支持相对友好。像字体渲染、Excel 兼容性处理、常用的中文函数习惯,团队实际测试下来,没有出现某些国外开源组件那种“一看就是洋玩意儿”的割裂感。对于国内团队做管理系统,这个体验差距还是能感知到的。

2. 选型对比与核心设计解读

2.1 选型时真正比拼的维度

表格组件这种基础能力,一旦集成到业务里,后面再换的成本极高。所以选型阶段不能只盯着 demo 好不好看,我当时列了几个硬指标。

  • 数据模型是否独立。表格的渲染 UI 可以换,但数据模型是核心。Univer 把命令系统和数据模型做成了独立模块,UI 只是数据的一种呈现方式。这带来一个很大的好处:我们可以通过 API 直接操作数据,不碰 UI,非常适合自动化测试和无头场景。
  • 性能是否有明确的工程手段支撑。Univer 用 Canvas 渲染,辅以视口裁剪和按需绘制,保证大表格场景下的交互流畅度。这一点在后面的实测中确实验证了。
  • 公式引擎的兼容深度。公式是表格的灵魂。Univer 提供了自研公式引擎,兼容大量 Excel 常用函数,并且支持动态数组公式。对于内部填报场景,我们最常用的 SUM、VLOOKUP、IF、ISNUMBER 这些函数都跑得很稳。
  • 扩展能力。Univer 的插件机制非常接近 VS Code 的设计思路——开发者可以注册自定义命令、自定义 UI、自定义单元格类型。这一点在业务改造中价值极大,因为真实业务不会满足于“能填数就行”,经常会要求单元格里放按钮、放关联数据、做联动校验。

2.2 Univer 的整体架构思路

Univer 的架构可以粗略分成三层:底层是核心数据管理模块,包括工作簿、工作表、单元格、样式、命令系统;中间层是业务能力插件,比如公式、协同、导入导出、条件格式;上层是 UI 呈现层,负责渲染、交互、快捷键、菜单项。

这种分层一个很实际的好处是:你可以把 Univer 嵌入到一个 React 项目里,也可以放在 Vue 项目里,甚至剥离 UI 在 Node 环境里操作数据。我们实际就是这么干的——前端页面负责交互,后台服务在特定场景下直接调用 Univer 的数据处理能力对上传的文件做解析和二次计算,两边共享一套数据语义。这在以前用纯 DOM 表格组件的方案里很难做到。

在命令系统方面,Univer 的设计也很有意思。用户每次操作都会被封装成一条命令,命令经过校验后执行,并同步产生可追溯的变更记录。这样做让“撤销重做”变得自然,也为协同编辑提供了基础——每个客户端的操作都能转化为可以被同步和合并的命令序列。理解了这个思路,再去配置协同服务,就不会觉得那是一个魔法黑盒。

2.3 渲染引擎为什么重要

我见过不少开发者在选题时第一句话就是“我们数据量不大,不需要性能优化”。这个想法在真实业务里往往会翻车,因为“数据量不大”的标准会随着业务发展迅速刷新。我们内部有一张库存台账表,几年下来已经积累了二十多万行数据。如果用传统 DOM 表格渲染,光是创建单元格节点就能把浏览器内存吃满,滚动时更是惨不忍睹。

Univer 的 Canvas 渲染方案,等于把“画表格”这件事从 DOM 层面解放出来。它维护了一个可视区域的概念,只绘制当前视口内以及边缘缓冲区的单元格,滚动时通过重绘而不是创建新 DOM 节点来更新画面。实测中,二十万行数据的表格,在普通办公笔记本上滚动缩放都没有明显的卡顿感。这个体验一旦习惯了,就回不去了。

当然,Canvas 渲染也有代价,比如文本选择、输入法处理、无障碍支持都需要额外实现。Univer 在这些细节上处理得比较成熟,中文输入法下的组合输入、光标位置跟踪都没有遇到明显异常。这背后付出的工程成本,是评价一个开源项目质量时容易被低估的部分。

3. 从零接入 Univer 的实操过程

3.1 环境准备与依赖安装

我们是 Vite + Vue 3 的前端技术栈,按官方推荐的 preset 方式接入。Univer 目前的包管理思路比较现代,按需引入核心模块,不会一股脑把全部功能塞进 bundle。安装阶段主要拉取的是 @univerjs/presets、@univerjs/core、@univerjs/sheets、@univerjs/ui 这一套核心依赖,如果要用导入导出,再追加对应插件。

npm install @univerjs/presets @univerjs/core @univerjs/sheets @univerjs/ui

这里有个值得注意的细节:Univer 对构建工具的版本有要求,尤其是 Vite 和 TS 版本。我们一开始在旧项目里直接装,结果编译时报了一堆类型错误。后来排查发现是 Vite 版本太旧,导致依赖树解析方式和 Univer 不兼容。建议在新项目或者升级过构建工具的环境中集成,省得自己折腾。

安装完成后,还需引入对应样式文件。Univer 有一套完整的主题变量体系,默认主题和暗色主题都支持。样式文件丢失是新手最容易遇到的现象,表现是表格能渲染但布局错乱、菜单没有样式,第一反应是代码写错了,实际检查一下样式引入基本就能解决。

3.2 初始化并渲染一张电子表格

初始化 Univer 的核心逻辑非常简洁,先创建一个 Univer 实例,再注册 Sheet 插件并设置工作簿配置。大致结构如下:

import { createUniver } from '@univerjs/presets/create-univer'; import { UniverSheetsPlugin } from '@univerjs/presets/sheets'; import '@univerjs/presets/lib/styles.css'; const univer = createUniver({ locale: 'zhCN', plugins: [ UniverSheetsPlugin({ selections: { enable: true, }, }), ], }); univer.createUnit( univer.createUnitByConfig({ name: '库存台账', sheets: [ { name: 'Sheet1', rowCount: 2000, columnCount: 200, cellData: { 0: { 0: { v: '物料编码' }, 1: { v: '物料名称' }, }, }, }, ], }) );

这一段代码做的是:创建一个电子表格单元,指定工作簿名称、工作表和初始数据。cellData 使用行索引和列索引定位单元格,v 字段表示单元格的原始值。相比在创建时塞一大堆数据,更常见的做法是先创建空表,再通过 API 按需注入数据,这样页面的初始渲染更快。

如果业务系统有自己的数据格式,Univer 也提供了一系列数据转换和填充的方式,比如通过命令系统批量写入。我们当时把后台返回的 JSON 数组做了映射,即按表头字段名把数据逐行写入,整个过程不涉及 DOM 操作,代码路径很干净。

初始化完成后,你会得到一个完整的表格界面,包括顶部工具栏、公式栏、名称框、工作表标签栏和右下角的状态栏。默认的交互能力已经覆盖日常填表需求,等于零成本获得了一个可用的在线表格 UI。

3.3 导入导出与公式配置

内部系统最硬的需求之一,就是能和 Excel 进行数据交换。以前下载模板、填表上传的流程倒还好,现在用户直接在网页里编辑,编辑完必须能把结果导出成 .xlsx 发给外部协作方。Univer 官方提供了导入导出插件,支持解析和生成 xlsx 文件。

实操上,导出功能可以绑定到自定义按钮上。点击按钮时,Univer 会基于当前工作簿的数据和样式生成 Blob 对象,再借助前端下载逻辑保存为本地文件。这里有一个实践经验:导出大文件时动作本身是同步的,如果工作簿数据量很大,建议加一层 loading 状态,避免用户以为卡死了。

公式配置则更加简单,单元格填写的字符串如果以等号开头,Univer 会自动交给公式引擎计算。更实用的是通过 API 写入公式,比如在合计行写入:

univer.getActiveUnit().setCellValue(10, 5, '=SUM(F2:F10)');

这里 10 是行索引、5 是列索引。公式引擎会把跨单元格依赖关系管理起来,数据变更时自动重算。对内部报表来说,SUM、AVERAGE、IF、ROUND、文本拼接这些高频函数足够覆盖绝大多数场景。动态数组函数在最新版本中也逐步支持,但如果你的业务重度依赖较偏门的函数,建议先在测试环境跑一遍用例确认兼容性再上线。

3.4 常见 UI 定制玩法

很多系统集成场景不希望用户看到完整的 Excel 风格工具栏,而是只保留业务需要的那几个按钮。Univer 的 UI 是插件化注册的,允许开发者对工具栏进行定制。我们实际做的是保留“撤销、重做、保存、导入、导出、格式刷”这几个高频操作,把大部分不相关的功能收进“更多”菜单,甚至直接隐藏。

自定义一个按钮的逻辑大致是:在 Univer 的 UI 插件中注册一个自定义按钮项,绑定点击事件后,通过 Univer 的命令 API 操作当前活动单元。比如我们加了一个“快速填充颜色”的业务按钮,点击后对选中区域统一设置底色,这个操作在业务上对应“标记异常数据”。

import { LocaleType, UniverInstanceType } from '@univerjs/core'; // 伪代码示例,展示注册自定义操作的思路 registry.command('mark-abnormal', { handler: (unitId, range) => { // 对选中区域批量设置样式 }, });

UI 定制这块最重要的经验是:动手之前先想清楚哪些功能是业务刚需,哪些是低频操作。表格组件的 UI 和业务耦合太深,后期维护成本会显著上升,尽可能只暴露必要入口,其余能力留给 API 层。

4. 性能表现与协同编辑的落地体验

4.1 大表格渲染实测

前面说 Univer 渲染性能好,不能光听宣传,还得看实测数据。我们的测试环境是一台 i5 处理器、16GB 内存的 Windows 办公笔记本,浏览器是 Chrome。测试用表包含 25 万行、18 列数据,每行 18 个字段,总单元格数超过了四百万。

实际验证下来,有几个直观感受:

  • 初次加载完整数据渲染,等待时间大约两秒左右,页面没有出现白屏或者冻结。
  • 滚动、选中、复制粘贴时,帧率比较稳定,没有明显的迟滞感。
  • 双击进入编辑状态、输入中文时,光标响应正常。
  • 对整列套用格式、设置条件格式后,重绘速度依然在线。

要强调一点,这种性能表现并不等于“无脑塞几百万行数据都不会卡”。Univer 采用了视口裁剪,但如果你写脚本一次性循环写入大量单元格数据,那一瞬间的调用开销仍然存在。更合理的做法是把数据分批写入,或者使用官方提供的批量更新接口。我们最后的方案是:用户打开表格时只加载当前业务需要的一个子集数据,比如本月的记录;需要全量分析时再触发异步加载和写入。这样既享受了 Univer 的性能优势,又不至于让网络传输和初始化过程背锅。

另外一个隐藏性能点是样式对象。如果你给每行单元格单独设置大量不同的字体、边框、底色,样式表的维护成本会显著上升。业务设计时尽量用“规范化的几个预设样式”,而不是让用户随意自定义每一格的字体大小和颜色。这既是产品层面的约束,也是性能层面的考量。

4.2 协同编辑的搭建思路

Univer 的协同编辑能力是它的一个大卖点,也是我们决定选用它的重要原因。多人同时打开同一张表格,任何一个人的修改实时同步到其他人的视图里。这背后的原理并不复杂,大致思路是:每个客户端的操作先转化为命令,命令发送到协同服务端,服务端负责命令的合并、冲突处理和广播分发。

搭建协同能力时,Univer 官方提供了一套协同示例工程,涵盖 WebSocket 服务端和前端接入层。我们在实际部署时,把 WebSocket 服务单独部署成一台内网服务,前端通过官方客户端库建立长连接,性能表现稳定,消息延迟基本在毫秒级。

这里有一个特别值得强调的经验:协同模式下,任何绕过命令系统直接修改数据的行为都会带来不可预期的冲突。刚开始我们有一个老接口,后台通过 API 直接更新数据库里的表格数据,再推前端刷新,结果多人同时编辑时频繁出现光标跳动、数据被覆盖的情况。后来把数据写入统一收口到 Univer 的命令体系里,协同冲突问题基本消失了。这也是理解 Univer 架构价值的关键点——命令不只是操作封装,更是协同一致性的基石。

限于篇幅,协同的具体部署细节我不在这里展开,因为这个主题单独写一篇长文都不过分。但可以负责任地说,如果只在局域网内部使用,协同服务的部署成本并不高;如果要做公网跨地域的实时协同,还需要考虑网络链路、服务容灾和权限体系,复杂度会上升一个级别。

5. 常见问题与排查技巧实录

5.1 快速排查速查表

集成过程中,我整理了一张问题速查表,按症状给出可能的方向,后续团队内部排查时非常管用。

症状可能原因解决方向
表格能渲染但完全没样式样式文件未引入或顺序不对检查 CSS 引入路径,确认在入口处最先加载
初始化后页面空白依赖包版本不一致统一版本范围,清缓存重装依赖
输入公式不计算公式栏与核心包未同时注册确认预置插件完整,确保公式引擎已启用
导入 xlsx 乱码或丢数据文件包含复杂格式或异常字符先用精简文件定位,再逐项关闭非必要样式
多人编辑数据互相覆盖绕过命令系统直接改数据将业务写入全部收敛到 Univer 命令体系里
自定义按钮消失了UI 定制与插件注册顺序问题确认自定义插件注册在 sheets 插件之后
暗色模式下工具栏看不清主题变量未切换到对应配置使用 Univer 官方主题切换 API,避免自定义样式覆盖

这张表不用死记,遇到问题时先判断是渲染层、数据层还是协同层的问题,基本就成功了一半。

5.2 我踩过的几个坑

挑三个印象最深的坑说说。

第一个是版本管理问题。Univer 迭代速度很快,有些示例代码用的旧版 API 在新版已经改名或者弃用。我们一开始照着网上教程写,初始化代码对不上,反复报错。后来养成一个习惯:无论从哪找到的示例,都以官方仓库里的示例代码为基准,先跑通最小用例,再逐步增加功能。这个习惯帮我避开了大量版本错位的坑。

第二个是数据批量写入的性能误区。我最初图省事,用一个循环逐格 setCellValue,结果一万行数据写入花了好几秒。后来查了社区讨论,改用批量更新的 API,一次性设置一个二维数组,速度提升非常明显。道理其实和数据库批量插入一样,减少和内核之间的调用次数永远是性能优化的首选方向。

第三个是协同场景下的缓存策略。我们一开始在浏览器里做了数据缓存,用户离线编辑后重新上线,直接把本地缓存整体推给服务端,结果和别人的修改产生了冲突覆盖。后来把缓存粒度降低到命令级别,离线期间的每个操作都作为独立命令同步。协同编辑不是“同步结果”,而是“同步过程”,这个认知转变让整个方案的稳定性上了一个台阶。

还有一点不算坑但值得提:Univer 的中文文档目前还在不断完善中,很多高级用法需要看英文文档和示例源码。好在其代码组织比较清晰,沿着插件注册、命令调用的脉络读代码,大部分问题都能在半个小时内定位到大致位置。如果有能力,向官方仓库提交 issue 或者直接参与讨论,也是一种很有效的学习方式。

写在最后

从需求评审到现在,Univer 已经在我们内部系统里稳定运行了几个月。最大的体会是,选一个基础组件不能只看 demo 炫不炫,要看它的数据模型、命令体系、插件机制这些“内功”是不是符合你的长期需求。Univer 这套设计,数据层与呈现层解耦,命令系统贯穿始终,插件扩展边界清晰,给业务后续的改造留下了足够的操作空间。

如果你只是在页面上展示一张静态表格,没必要上 Univer,杀鸡不用牛刀。但如果你的需求是网页内编辑、类 Excel 交互、多人协作、格式导入导出,甚至以后还想扩展成在线文档、在线幻灯片,那 Univer 值得你花一个下午好好研究一下。我给团队的建议是:先用最小 demo 验证核心场景,跑通后再谈深度集成。动手试一遍,比看十篇评测都管用。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进