Univer实战:实现指定单元格可编辑,其余锁定只读
发布时间:2026/10/2 16:15:28来源:尧图网络
做一个在线填表功能模板制作者把一张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 vitelatest univer-demo -- --template vue-ts cd univer-demo npm install这里我用的是Vue模板如果你用React思路完全一致Univer不挑框架。安装Univer时直接引入官方预设会更省事它会把表格、公式、UI这一层都组装好。npm install univerjs/presets univerjs/core2.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自带的界面把流程走一遍你会对锁定机制更有体感。选中允许用户填写的区域比如A2:C20。在单元格格式设置里找到“保护”相关选项把“锁定”取消勾选。右键点击左下角的工作表标签选择“保护工作表”。确认保护范围保存。做完之后用鼠标点击刚才取消锁定的区域可以正常输入点击其他单元格会提示该单元格已只读。这个交互就已经满足了“用户填一些单元格其他单元格无法修改”的原始需求。但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交互解耦。不要追求用上每一个新功能先把你最需要的“指定单元格填写、其余锁定”跑稳。等版本趋于稳定再考虑向协同、公式编排这些深水区扩展。这不仅是技术选型也是项目掌控力的问题。工具再强也不如把边界守清楚。
网站建设高端定制企业官网