☰
Univer:开源在线表格SDK,快速集成到Web应用
2026/11/5 6:20:29 网站建设 项目流程

如果你最近一直在逛 GitHub 或者关注前端圈,大概率刷到过这个名字:Univer。这个项目的热度涨得非常快,很多人在讨论“开源版的在线 Excel 能不能用来做真正好用的产品”。我自己的结论是,Univer 已经不只是当年那个表格插件的升级版,它是一套把在线文档体验搬进自家产品的可行性方案。这篇文章我会把 Univer 是什么、内部怎么拆、怎么快速集成、以及我实际踩过的一些坑完整写出来,希望能帮到正在选型或者准备动手尝试的人。

先说清楚一个概念,Univer 不是单纯的一页表格组件,它更像一个“办公套件 SDK”。官方定位是开源、可扩展、支持协同编辑的在线表格 / 文档 / 幻灯片统一方案。也就是说,你可以把它嵌入到自己的 Web 应用里,拿到一个带有工具栏、公式、条件格式、图表、协同光标等等能力的在线编辑环境。如果用一句大白话说:过去你想在自己的系统里做一个“像 Excel 一样能编辑、能计算、能多人协作”的模块,基本要写很多底层渲染和光标同步逻辑,现在 Univer 把这层能力抽象出来了,你要做的是把数据喂进去,然后把细节管理交给它。

1. Univer 到底是什么:它凭什么获得注意

1.1 不只是“又一个电子表格组件”

很多入门的朋友第一次看到 Univer,脑海里第一个念头是:它跟 Excel 有什么区别?其实这么对比不准确。Univer 的目标从来不是做一个离线的本地软件,而是给 Web 应用提供类似 Google Sheets 的体验,并且把能力拆成可以直接调用的 SDK 和插件体系。

它支持三种载体:表格(Univer Sheet)、文档(Univer Doc)、幻灯片(Univer Slide)。三个模块在底层共享同一套渲染引擎、公式引擎和协同机制,但业务逻辑彼此独立。这意味着你在自己的系统里只想要一个表格,可以只引入 Sheets 相关模块;如果后续想加一个可以多人编辑的文档模块,也不用重新搭一套架构,直接在同一个 Univer 实例里注册对应插件即可。

从应用场景看,Univer 的适用范围其实很宽:

  • 低代码平台需要一份可配置的在线表格作为列表编辑区;
  • 数据中台需要把报表结果导出成 xlsx,同时支持用户在浏览器里临时修改;
  • ERP 或 OA 系统需要内置一个“类 Excel”的预算编制页面;
  • SaaS 产品要提供模板编辑、批量录入、导入 / 导出功能;
  • 自建网盘或知识库需要一套在线的文档预览与编辑能力。

这些场景共同的特点是:不能直接用 iframe 嵌入一个完整 Office 应用,也不想被迫在浏览器里重写一个表格渲染逻辑。Univer 恰好就是在这里起作用。

1.2 Univer 在线与其他表格库的对比

如果你也在表格组件选型,大概率看过 Luckysheet、OnlyOffice、SheetJS 这类产品。它们看起来是同一个方向,但实际定位差别很大。

项目主打方向开源协议集成难度适合场景
Univer在线办公套件 SDKApache 2.0中等需要自定义界面 + 协同 + 文档能力的 Web 应用
Luckysheet在线表格组件MIT中等简单表格嵌入,不用依赖重型插件体系
OnlyOffice完整在线办公套件AGPL / 商业授权较大需要完整文档应用,能接受部署独立服务
SheetJS表格文件解析 / 生成库Apache 2.0小只需要读写 xlsx,不需要编辑器界面

我这里稍微展开说一下为什么会有这种区别。SheetJS 是“读写库”,它不是编辑器;Luckysheet 提供了编辑界面,但在渲染性能、多模块扩展和协同实现上,维护成本和上限相对有限;OnlyOffice 功能最全,但想要完全嵌入到自己的界面里,改造工作量非常大。Univer 的优势在于:它把自己的架构从第一天就设计成模块化的,不是把一堆功能堆在一个包里,而是让每个能力都可以被替换和扩展。

尤其值得注意的一点是,Univer 的主仓库一直保持活跃,且团队投入度很高。新版本迭代速度快,社区示例也在不断增加。做技术选型时,一个活跃的社区比现成功能更重要,因为表格这个场景太复杂,谁都没法保证一次交付就完全满足业务需求,后续的持续迭代和兼容性修复非常关键。

2. 拆解 Univer 的架构与核心模块

2.1 模块化设计:核心、渲染、公式、UI 的分层

Univer 的代码组织方式,是我认为它最值得学习的地方。和许多把“表格”做一个巨大类的前端库不同,它把职责分得很清楚:

  • @univerjs/core:核心数据模型、工作簿 / 工作表 / 单元格定义、依赖注入容器、命令机制;
  • @univerjs/engine-render:基于 Canvas 的渲染引擎,负责绘制单元格、边框、选区、控件;
  • @univerjs/engine-formula:公式解析、计算、依赖树、函数注册;
  • @univerjs/sheets:表格业务逻辑,包括行列操作、合并单元格、条件格式等;
  • @univerjs/docs:文档模块对应的业务逻辑;
  • @univerjs/slides:幻灯片模块;
  • @univerjs/ui:工具栏、右键菜单、弹窗等 UI 层组件;
  • @univerjs/collaboration:协同编辑相关能力。

这种拆法带来的直接好处是:如果你不需要公式引擎,那可以完全不注册它,减少打包体积;如果你需要换一套 UI 皮肤,也不用去动核心数据模型。依赖注入机制让每个模块都可以被替换为自定义实现,这一点对于集成进已有系统的场景特别重要。

我用一个生活化的类比来解释:Univer 核心是一个“业务中台”,渲染引擎、公式引擎和 UI 是三个可插拔的“渠道端”。业务数据永远存在核心模块,渠道端只是负责把数据显示出来、接受用户操作。这也保证了同一种数据可以被桌面端、Web 端、移动端共用。

2.2 Canvas 渲染引擎:为什么不用 DOM 表格

Univer 的表格主体渲染并没有采用传统的<table>或<div>网格方案,而是使用 Canvas 绘制。很多人第一次听到这个会有点担心,觉得 Canvas 在处理文本选择、输入框定位、无障碍访问时会不会很麻烦。实际体验下来,这个选择是合理的。

表格和普通页面不同,它可能一行有几百列,一屏只能显示一小部分。如果每个单元格都生成独立的 DOM 节点,一万行数据就会产生几十万个节点,浏览器直接卡死。Canvas 方案下,屏幕区域只绘制当前可视范围内的单元格,滚动时不断重绘局部区域,理论上百万行数据的渲染压力也不至于让页面崩溃。

当然,代价也存在:在 Canvas 里实现单元格内编辑光标、选区高亮、拖拽填充、自动调整行高列宽等交互,都要自己做命中检测和坐标计算。这也是为什么 Univer 的渲染引擎本身就是一个相当重的模块。从实际使用看,它处理得相当流畅,滚动时没有明显的视觉闪烁,基本达到了在线表格应有的手感。

2.3 公式引擎与命令机制

Univer 内置了相当完整的公式系统,常用函数如 SUM、VLOOKUP、IF、SUMIF 等都可以正常使用。它的公式引擎不只是简单地在输入框后面接一个计算结果,而是维护了一套依赖关系,单元格引用的变化会自动触发相关公式重新计算。这也是在线表格最容易被低估的部分:一旦公式数量多、跨工作表引用复杂,计算顺序和更新粒度就非常考验架构。

我用一个例子说明依赖链的意义:A1 单元格输入=B1*2,B1 的值又被 C1 的公式决定。当修改 C1 时,正确的行为是 C1 先算出来,然后 B1 跟着更新,最后 A1 再更新。如果模块之间没有依赖管理,就会出现一次性把整个表格所有公式全部重算的性能灾难。Univer 的做法是建立公式之间的依赖关系图,只重算真正受影响的单元格。

另外,Univer 内部的操作几乎都通过命令机制完成。用户在界面上执行的动作,比如插入行列、修改单元格、合并单元格,会被包装成结构化命令。命令可以被撤销、重放、同步。这套机制最大的价值在于协同:当多个用户同时对同一份表格进行操作时,服务端可以接收这些命令,按顺序合并,再广播给其他客户端,而不是把整个表格文件传来传去。

3. 5分钟在 Vite 项目里集成一个 Univer 在线表格

3.1 环境准备与依赖安装

纸上谈兵没意思,我直接给大家演示一遍怎么把 Univer 跑起来。我用 Vite + TypeScript 做一个最小示例,组件库的版本以当前最新 stable 为例。假设你已经装好了 Node.js 18+。

npm create vite@latest univer-demo -- --template vanilla-ts cd univer-demo npm install npm install @univerjs/preset-sheets

这里的@univerjs/preset-sheets是官方提供的预设包,把创建表格所需的渲染引擎、基础 UI、公式引擎都打包在一起了。如果你要做精细裁剪,可以按上一节讲解的方式分别安装各个子模块,这里先以最快跑通为目标。

3.2 初始化 Univer 实例

安装完成后,打开src/main.ts,输入下面的代码:

import './style.css'; import { Univer } from '@univerjs/preset-sheets'; import '@univerjs/preset-sheets/lib/styles.css'; const univer = new Univer({ locale: 'zhCN', }); const sheet = univer.createUniverSheet({ data: { 'Sheet1': { name: 'Sheet1', rowCount: 100, columnCount: 20, cellData: {}, } } });

对应地在 HTML 里放一个容器,并给它设置宽度和高度:

<div id="app" style="width: 100%; height: 600px;"></div>

然后启动开发服务:

npm run dev

打开浏览器,你就能看到一个完整可编辑的表格页面,顶部有工具栏,左侧有行号栏,切换单元格可以直接输入内容。这里有两个容易被新手忽略的细节:第一,容器必须设置明确高度,否则渲染引擎拿不到视口尺寸,表格会显示不出来;第二,不同版本的 API 命名略有差异,建议参考官方示例文件,不要直接从老项目复制。

3.3 加载数据并定制工具栏

大多数业务场景不会从一张空表开始,而需要把已有的数据展示出来。你可以通过cellData传入初始值,也可以创建后通过 API 操作某个单元格:

const cell = sheet.getCell(1, 1); cell.setValue({ v: '你好,Univer', });

如果你要把 Excel 文件里的数据导入进来,Univer 也提供了导入解析能力。把文件转成 ArrayBuffer 后交给对应解析插件即可,它会自动还原单元格内容、样式、合并区域和基本公式。我实际测试下来,常规的 xlsx 文件还原效果很好,但不同版本的 Excel 生成文件在细节上会有差异,比如某些自定义格式、条件格式规则、图表可能无法 100% 还原。这个问题几乎存在于所有前端表格方案,不只是 Univer,所以不用太苛责。

工具栏是另一个关注点。默认工具栏按钮很多,包括撤销、重做、字体、颜色、对齐、筛选等。如果你的业务不需要某些功能,可以在 UI 配置中关闭对应项,避免用户看到用不了的按钮,也减少理解成本。

const sheet = univer.createUniverSheet({ data: {...}, toolbar: { undo: true, redo: true, font: false, align: true, filter: false, } });

具体属性名可能会随版本调整,但思路是明确的:一切 UI 组件的显隐都可以控制,不要直接改源码。

3.4 “Univer 在线”的核心价值:协同怎么接

标题热词里的“univer在线”,我理解是指它在网页里就能完成多人协作编辑这件事。要发挥这个能力,不能只靠前端静态库。传统做法是多人编辑同一份 Excel 文件,通过文件锁或版本号避免冲突,体验很差。Univer 的思路是让每个用户的操作变成一个命令,命令同步到服务端,服务端再广播给其他在线客户端。

实现协同有两种路径。第一种是使用 Univer 官方的协同服务与配套插件,部署后把前端实例连接上去,这种方案对团队开发者最友好,开箱即用。第二种是自己搭建消息通道,前端实现命令的发送与接收,后端负责存储、排序和冲突合并。后一种方式扩展性强,但需要关注选区间冲突、操作版本号、断线重连等细节。

我建议小团队先用第一种,把核心业务跑通后再考虑自研。协同的复杂度和数据规模成正比:两个人编辑同一个单元格时,合并逻辑相对简单;一百个人同时操作一张几万行的大表,就需要做操作转换和结果排序。这不是一个可以拍脑袋实现的功能。

4. 我踩过的坑与排查建议

4.1 容器高度和视口校准

我在第一个 Demo 里遇到过表格只显示出一部分、甚至完全空白的情况。排查后发现,是父容器的height没有设置。Univer 的渲染是基于 canvas 的,canvas 的初始尺寸必须依赖容器尺寸,容器为 0 时,表格内部绘制区域的坐标全是 0,自然看不到内容。

解决方式很简单:给容器设置固定高度,或者在页面布局完成后调用一次univer.refresh(),让它重新测量高宽。如果你把表格放在 Tabs 切换页里,也需要注意:默认隐藏的 Tab 容器宽度高度都是 0,切换到该 Tab 时表格可能还是空白,需要在切换事件里触发一次刷新。

4.2 API 版本变化快,多读官方更新日志

Univer 的 API 目前还处于快速迭代阶段。我在网上搜到的一些旧教程,代码里写的还是@univerjs/base-sheets、@univerjs/main-thread-plugin,这些包在最新版本里已经改名或者合并了。如果你按照旧示例安装依赖,npm 会报各种找不到模块的错误,或者装了之后初始化方法不存在。

我的建议是:如果项目从零开始,直接安装最新版 preset;如果是老项目升级,一定要看官方迁移指南。不要盲目相信几年前的博文,我自己的很多笔记现在也已失效,兼容层不是这个项目的重点。

4.3 导入 xlsx 后的样式和公式问题

导入 xlsx 是表格场景里最常见的需求,也是问题最多的点。Univer 对基础样式解析支持得不错,但我遇到过一个典型问题:从某个国产 WPS 导出的文件,数字类型被识别成字符串,导致公式计算出现#VALUE!。排查后发现,这类文件在单元格类型标记上与标准 Excel 存在差异,Univer 解析时按字符串处理了。

遇到这种情况,不要想着让解析器无所不能,而是要在业务层做数据类型清洗。导入后遍历一次数据,把看起来是数字的字符串转成数字,同时修改单元格类型标记。另外,如果最终表格需要重新导出 xlsx 给用户下载,建议保留一份规范导出测试样例,每次发版前跑一遍导出比对,避免功能和样式回退。

4.4 性能优化与大数据量展示

Univer 虽然用 Canvas 做了虚拟渲染,但一次性把十万行数据放进cellData依然会带来初始化耗时。业务上要做分片加载:首次只加载前一百行,滚动到接近底部时再追加后续数据。Univer 提供了 API 增量更新单元格数据,这样可以避免页面打开时白屏时间过长。

还有一个容易被忽略的点是单元格样式。很多人喜欢复用 Excel 里那种单元格套模板的做法,每行设置不同背景色,这会导致样式的合并和计算压力变大。如果表格要支撑大量数据,尽量让样式集中在工作簿级和列级,少用逐单元格级样式,渲染性能会明显更好。

5. 写在最后:选型与扩展感受

我实际用 Univer 做的项目已经稳定运行了一段时间,整体印象是:它确实把“在 Web 应用里嵌入一套表格办公能力”这件事的工程成本降低了一个档次。相比完全自研,Univer 帮我们省掉了 Canvas 渲染、公式解析、撤销重做、协同同步这些最耗时间的部分,让我可以把精力聚焦到业务功能本身。虽然它在个别领域还有改进空间,比如复杂图表模板的还原度、专属定制工具栏的文档清晰度,但这些并不影响它作为核心方案的价值。

如果你也在评估要不要用 Univer,我的建议是先不要纠结它不具备某些高级功能,而是用小 Demo 验证自己对它的改造能力。实际跑一个包含数据初始化、工具栏定制、文件导入导出的完整流程,比看一万字技术分析更有说服力。我的个人经验是:这类开源办公套件,选型的成败往往不在第一天跑通,而在你往里面塞真实业务数据的那一刻还能不能保持流畅。Univer 在这方面的表现,值得一试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询