news 2026/10/2 16:15:28

Univer实战:实现指定单元格可编辑,其余锁定只读

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Univer实战:实现指定单元格可编辑,其余锁定只读

做一个在线填表功能,模板制作者把一张Excel发给我,要求是:用户能填“姓名、电话、备注”这几列,但“评分、审核意见”这些列绝不能动。一开始我以为就是套几个input框,真正做完才发现,从单元格锁定、工作表保护到权限控制,每一步都有坑。后来换成了univer这个开源在线表格方案,事情才变得可控。

这篇文章不写PPT式的功能介绍,只聊两件事:univer能拿来做什么,以及怎么把一个“用户只能填指定单元格,其余锁定只读”的真实场景落地。适合正在做B端表单、数据填报、后台表格引擎的项目负责人和前端开发。

1. 我为什么关注Univer:开源表格组件这片市场已经散得太久了

1.1 以往要在线表格,基本只有两条路:缝缝补补和重金采购

做在线表格的人都知道,HTML table只适合看,不适合编辑。真正要支持录入、复制粘贴、公式、合并单元格,几乎都得自研或者用现成的表格组件。

早期我用过一些纯前端方案,它们的特点是“表面像表格,内里还是一堆DOM”。单元格一多,滚动卡顿;Excel文件导进来,样式丢大半;想锁定某些区域,要么自己算坐标,要么在事件里拦截。维护成本非常高,而且每加一个需求,就得动一遍渲染层。

另一条路是采购商业表格控件。功能确实全,但单价高,而且很多核心能力是黑盒,遇到问题只能提工单。最难受的是授权模式,一个项目套一个授权,做成SaaS产品后每个租户都要算一遍License。长期来看,这笔账并不便宜。

univer出现在这个节点上,等于给中间地带补了一个选项:开源、可嵌入、组件化,而且不是那种只做“单元格展示”的玩具,而是把公式、样式、多表格、数据验证这些引擎能力做了进去。

1.2 Univer的核心思路:引擎与UI彻底解耦,而不是又一个组件库

我第一次看Univer架构时,最大的感受是它不像“插件”,更像“框架”。Univer把一套完整的办公套件内核(文档、表格、幻灯片)抽离出来,渲染层用Canvas重绘,业务逻辑放在独立插件包里,跟宿主框架完全无关。

这意味着什么?你在React项目里可以嵌入,在Vue项目里可以嵌入,哪怕只是用原生JS写一个静态页面,也可以嵌入。它不绑定你现有的技术栈,这是很多同类组件做不到的。

Univer的数据模型也接近Excel的语义:工作簿、工作表、单元格、范围、样式、公式,都是结构化对象。前端拿到的是数据,而不是一堆乱七八糟的DOM节点。这为后面做“指定单元格锁定”提供了很好的基础,因为锁定的前提是:我能精确描述任何一个单元格的位置和状态,而不是靠UI状态去硬记。

1.3 和Luckysheet、Handsontable、SpreadJS放在一起看

维度UniverLuckysheetHandsontableSpreadJS
开源/免费Apache-2.0,核心代码开源MIT,但项目已明显放缓开源版GPL,商用需购买授权纯商业授权
框架绑定不绑定,React/Vue/原生均可偏向原生和Vue封装React封装成熟依赖自家体系较深
渲染方式Canvas渲染,支撑大数据量Canvas+部分DOMDOM渲染为主Canvas,偏重传统桌面体验
公式能力内置较多函数,兼容Excel语义公式能力一般有公式但偏基础公式很强,毕竟是老牌商业控件
学习与定制成本插件机制清晰,适合二次封装改渲染层很吃力改交互容易,重逻辑费劲定制只能走官方API

坦白说,没有谁是完美的。Univer的优势在于它的底子更现代,插件化方式对开发者更友好;缺点也很明显,版本迭代快,API变动频繁,网上能找到的中文资料深度不够。这就更需要把实践步骤和坑记录下来。

2. 上手跑通:用Vite加TypeScript把Univer嵌进自己的页面

2.1 最小工程怎么建

我建议用Vite加TypeScript起步,别一开始就引入复杂脚手架。原因很简单:Univer是典型的前端重逻辑库,TS类型能帮你提前发现很多API误用,Vite的按需编译也能让开发期反馈更快。

npm create vite@latest univer-demo -- --template vue-ts cd univer-demo npm install

这里我用的是Vue模板,如果你用React,思路完全一致,Univer不挑框架。安装Univer时,直接引入官方预设会更省事,它会把表格、公式、UI这一层都组装好。

npm install @univerjs/presets @univerjs/core

2.2 写一个能正常渲染的入口

Univer的预设方案给了一个很友好的入口:createUniverBasic。它会自动注册工作簿所需的插件,我们只需要把容器节点传进去。

import { createUniverBasic } from '@univerjs/presets'; import { LocaleType } from '@univerjs/core'; import '@univerjs/presets/lib/styles.css'; const univer = createUniverBasic({ container: document.getElementById('app') as HTMLDivElement, locale: LocaleType.ZH_CN, });

这一步跑通后,页面上会出现一个完整的在线表格:工具栏、工作表标签、选区、公式编辑栏都有。如果你用的是不同类型号,记住你的版本里偏细节的API可能有出入,但只要沿着预设方法走,大部分情况不会太离谱。

2.3 把自定义的模板数据塞进表格

创建空表格只是第一步,实际业务需要“打开”一个可编辑模板。Univer加载数据的方式是把工作簿数据对象传给实例创建,直观理解就是把一个JSON结构丢给表格引擎。

const univer = createUniverBasic({ container: document.getElementById('app') as HTMLDivElement, locale: LocaleType.ZH_CN, }); univer.createUniverSheet({ sheets: [ { name: '登记表', rowCount: 50, columnCount: 10, cellData: { 0: { 0: { v: '姓名' }, 1: { v: '电话' }, 2: { v: '备注' }, 3: { v: '评分(只读)' }, }, 1: { 0: { v: '' }, 1: { v: '' }, 2: { v: '' }, 3: { v: '90' }, }, }, }, ], });

这里的cellData结构就是行号对应列号,单元格内容是{ v: 值 }。注意,cellData是Univer内部最常打交道的数据结构,后面做锁定、样式修改、数据回填都会围绕它展开。

写这一行代码时,我建议顺手把版本固定下来。Univer目前还处于快速迭代阶段,今天能用的API,下个小版本可能就改了名字。我的习惯是锁版本号,升级时专门看Changelog,而不是等着意外打破。

3. 落地“用户填指定单元格,其余锁定只读”的整个流程

3.1 先把锁定和保护这两个概念弄清楚

很多人在这一步栽跟头,是因为分不清“锁定单元格”和“保护工作表”。简单说:

  • 所有单元格默认都处于“锁定”状态,但这个状态在没有保护机制时不起作用,用户依然能编辑。
  • 只有当你“保护工作表”之后,锁定的单元格才真正变成只读,那些被设置成“取消锁定”的单元格依然允许填写。

这就解释了为什么有些人设置了半天,发现所有单元格还是能改:他只是改了单元格的锁定属性,但根本没用文件保护去激活它。

我把这个机制做成了一张直观的逻辑对照:

单元格锁定状态工作表保护状态用户实际效果
默认锁定未保护可编辑
手动取消锁定未保护可编辑
默认锁定已保护只读
手动取消锁定已保护可编辑

这个设计其实是传统的Excel保护模型,Univer继承了同一套语义。理解了它,你就能处理90%的“可填不可改”需求。

3.2 用UI快速做一个“可填写区域”模板

先别急着写代码,用Univer自带的界面把流程走一遍,你会对锁定机制更有体感。

  1. 选中允许用户填写的区域,比如A2:C20。
  2. 在单元格格式设置里找到“保护”相关选项,把“锁定”取消勾选。
  3. 右键点击左下角的工作表标签,选择“保护工作表”。
  4. 确认保护范围,保存。

做完之后,用鼠标点击刚才取消锁定的区域,可以正常输入;点击其他单元格,会提示该单元格已只读。这个交互就已经满足了“用户填一些单元格,其他单元格无法修改”的原始需求。

但UI操作适合演示,真实项目必须走API。因为模板是后端下发的,每次生成的区域可能不同,我们不能指望管理员手动去点。

3.3 用API控制工作表的保护状态

在Univer中,修改保护状态最核心的是SetWorksheetProtectionMutation这一个命令。它的作用是设置某个sheet的保护配置,包括是否开启保护、哪些操作被禁止。

import type { Workbook } from '@univerjs/core'; import { SheetExtension } from '@univerjs/sheets'; async function enableSheetProtection(univerInstance: any, unitId: string, sheetId: string) { await univerInstance.getCommandService().executeCommand( 'sheet.mutation.set-worksheet-protection', { unitId, subUnitId: sheetId, protection: { protect: true, permission: { select: true, edit: false, }, }, } ); }

这段代码表示:开启保护,允许选区操作,禁止编辑。Univer的权限还支持配置是否允许排序、筛选、插入行列等等,但对我们这个场景,核心就是edit: false。

注意,Univer不同小版本对命令ID和参数结构的命名可能微调。如果你在自己的工程里执行后没有生效,最有效的排查办法是打开浏览器控制台,手动用Univer的UI开启一次保护,观察Network面板或调试信息里出现了什么命令,再用你实际的命令ID去替换。

另外,Univer的编辑器在“锁定”这个细节上,需要预先保证需要填写的区域是“取消锁定”状态。API层面,如果你的模板数据已经通过JSON加载,可以在初始化数据时直接把可编辑区域的locked属性设为 false。比如某个单元格:

cellData: { 1: { 0: { v: '', locked: false }, }, }

不过要提醒的是,在Univer当前版本中,锁定属性更多是配合保护命令生效的。只在样式层设置了locked而没开启保护,用户依然能编辑。两者缺一不可。

3.4 不同登录用户看到不同可编辑区域

项目越做越深时,你会发现“用户”不是一个统一的群体。A角色只能填A列,B角色只能填B列,这是最常见的权限需求。

我目前的做法是用Univer的“多工作表”能力配合保护策略:给不同的角色准备不同的工作表,每张表只解锁该角色负责的区域,其余区域全部锁定。用户登录后,根据角色动态加载对应的工作簿数据,或者隐藏掉不该看的工作表。

更细的颗粒度可以做到单元格级权限,但那通常需要组合权限服务和后端鉴权,复杂度会明显上升。我的建议是:先评估业务是否真的需要单元格级权限,如果只需要“某些列可编辑”,用多sheet方案最稳妥,性能也更好。

3.5 别忽略服务端的校验边界

这里必须泼一盆冷水:Univer做的“锁定”是前端交互层面的保护。它让普通用户无法在界面上修改,但它挡不住懂技术的人绕过前端直接调用后端接口,往被锁定的单元格写数据。

所以,严格意义上说,Univer负责的是“体验和约束”,服务端必须在接收数据时再次校验:哪些单元格允许被这个用户修改,哪些字段必须原样返回。这就像门锁,它防的是顺手推门的人,不是防着破墙而入的人。

如果项目对数据一致性要求很高,建议后端保存模板定义时,同时记录“可编辑区域清单”,提交数据时逐格校验。别把信任完全交给前端表格组件。

4. 实际接入Univer时踩过的几个坑

4.1 版本之间API漂移,远比想象中严重

最典型的是:上个月还能用的executeCommand参数,升级一个小版本后,命令ID直接变了。Univer把命令分成了交互命令和基础命令,不同插件包可能导出不同的常量,如果你按旧版文章写死字符串,就会在运行时报错。

我现在的对策是:把Univer相关调用尽量收敛到一个独立模块里,对外只暴露enableProtection(sheetId)、disableProtection()、setCellData()这类业务方法。以后换API,只改这一个模块,不至于全项目搜字符串。

这算不算过度设计?以Univer目前的速度看,完全有必要。

4.2 设置“取消锁定”时,误把整行样式重置

有一次我在初始化数据时把一整行的单元格样式统一设置,结果覆盖了之前单独处理的锁定状态。代码只设置了字体加粗,但因为传入的样式对象不完整,Univer把这一行所有单元格的 locked 属性都重置成了默认值。保护开启后,原本开放的填写区域也变得不可编辑。

排查了很久才定位到:单元格样式是完整覆盖的,更新时没有合并旧的locked属性。后续所有类似操作,我都会先读取单元格当前样式,再合并新属性,避免踩踏:

const currentStyle = cell.getStyle(); cellData[row][col] = { v: value, s: { ...currentStyle, locked: false }, };

4.3 大数据量加载时首屏白屏,渲染配置被忽略

表格行数多、样式也多的时候,Univer渲染压力会变大。我试过一次性加载几百行带边框、底色、公式的模板,首屏等待时间明显变长。

Univer的Canvas渲染虽然在滚动性能上比DOM方案强很多,但初始化数据量仍然需要控制。实际做法是:先加载用户可见区域的数据,其余行列延后填充;涉及超大数据量时,关闭网格线的选项也有一定收益。这不是Univer的bug,而是所有表格引擎的正常权衡。

4.4 样式表忘记引入,工具栏成了一片空白

这是个很低级但很常见的错误。只安装了JS包,没引@univerjs/presets/lib/styles.css,页面会出现一个功能正常但没有任何UI样式的“裸表格”。所有图标位置都是空白,按钮点了有效果但看不见。

排查方法也比较直接:打开控制台看有没有加载CSS文件的404。Univer的样式体系是独立打包的,不同入口需要对应不同的样式文件,这一条基本次次踩,记住了就不用再浪费时间。

5. 从嵌入到在线协同:Univer到底能做多深

5.1 起初的只读与锁定,只是Univer能力里的很小一块

如果你只把Univer当成“单元格只读控件”,确实有些大材小用。它本身支持公式计算、条件格式、数据验证、多级撤销、打印等,这些能力对做表单和业务系统是实打实的加分项。

比如数据验证,可以在用户填错格式时直接拦截;公式可以自动算出某些统计字段。配合保护机制,公式列设为锁定,用户只能填源数据,计算结果自动更新,这个体验比后端穷举计算要舒服太多。

5.2 真正的多人协同需要更谨慎的选型

很多人看中Univer就是冲着“在线协同”来的。但要注意,开源版默认更多承担的是客户端渲染和单机编辑,真正要支持多人同时修改同一张表,需要额外的协同服务端支撑,官方把协同能力放在了SDK版本里。

如果你的项目确实需要多人在线实时编辑,不能只装一个开源包就指望搞定。建议提前跟官方确认授权方式和接入成本。如果是内部工具或者面向少量用户,先做单机编辑加手动刷新,也足够扛过MVP阶段。

5.3 我对Univer的未来看法与当前使用建议

我的整体判断是:Univer已经跳出了“又一个表格组件”的层次,它在把整个办公套件的内核做成开源基础设施。短期看,API不稳定是最大的隐忧;长期看,这反而是社区生态活跃的表现。

对想直接用的人来说,我的建议是:锁定版本,做好封装,把模板数据、权限规则和UI交互解耦。不要追求用上每一个新功能,先把你最需要的“指定单元格填写、其余锁定”跑稳。等版本趋于稳定,再考虑向协同、公式编排这些深水区扩展。

这不仅是技术选型,也是项目掌控力的问题。工具再强,也不如把边界守清楚。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 16:15:26

Kettle 9.3 生产级部署避坑指南:驱动、时区、JSON与Linux定时任务

简介:本资源为Kettle 9.3最新版官方安装包百度网盘下载指南文档,面向数据工程师、ETL开发人员及大数据初学者,解决国内用户因网络限制难以获取Pentaho官方资源的痛点。文档以结构化方式详解Kettle核心能力(跨平台运行、图形化Spoo…

作者头像 李华
网站建设 2026/10/2 16:14:28

Verilog条件语句优先级解密:if与case综合后的硬件行为差异

开门见山说一句:Verilog里的if和case,写的时候只是几行代码,但综合出来的电路优先级结构可能完全不一样,甚至同一段代码在不同的上下文里会有截然相反的硬件行为。我见过不少同事在这个问题上吃过亏,仿真一点问题没有&…

作者头像 李华
网站建设 2026/10/2 16:14:09

Codex 运行报错排查指南:十类高频问题与解决方案

1. 装完 Codex 却跑不起来,问题到底卡在哪Codex 这类命令行 AI 编程助手,装完之后敲下第一条命令就报错,几乎是每个新手都会经历的阶段。我自己第一次在 VSCode 里配 Codex 的时候,光是让它正常响应第一条请求就折腾了将近两个小时…

作者头像 李华
网站建设 2026/10/2 16:14:06

ECharts Tooltip配置详解:从基础到自定义富文本实战

1. ECharts Tooltip:数据可视化里最容易被低估的细节做前端数据可视化这行,有个特别有意思的现象:很多开发者能花大量精力去调图表的颜色、坐标系、数据样式,却往往忽视了光标悬停在图表上时那个小小的提示框——tooltip。但恰恰是…

作者头像 李华
网站建设 2026/10/2 16:13:45

群晖ABB整机恢复实战:从备份到裸机还原的完整实验手册

1. 先说结论:备份配好了,不等于灾难来临时能恢复我其实是被一次真实的教训逼着做这个实验的。前两年公司一台跑了财务系统的Windows Server 2016物理机,凌晨三点系统盘直接亮黄灯,第二天上班时已经进不去系统了。当时群晖NAS上的A…

作者头像 李华
网站建设 2026/10/2 16:13:27

OpenRIG 开源AI网关实战:多模型统一接入、路由与故障转移

1. 先搞清楚:OpenRIG 是做什么的 这两年做 AI 应用,最让人头大的不是模型能力不够,而是模型太多了。今天用 OpenAI,明天想换 Anthropic,后天客户要求必须走国产模型。每个供应商一套 SDK、一套鉴权、一套计费逻辑&…

作者头像 李华