ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

深入解析 @univerjs/slides:Univer 演示文稿核心数据模型与插件架构

2026/9/14 18:27:25 拓冰建站 浏览量
深入解析 @univerjs/slides:Univer 演示文稿核心数据模型与插件架构 深入解析 univerjs/slidesUniver 演示文稿核心数据模型与插件架构【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univer本篇技术指南聚焦 Univer 全栈办公框架中的演示文稿核心包univerjs/slides围绕其在仓库中的 README 展开该包不提供任何 UI 与国际化资源而是承载幻灯片Presentation/Deck的核心数据模型与基础服务是 Univer Slides 的能力底座。读完本文你将掌握该包的安装接入方式、插件注册与依赖关系、SlideDataModel的页面管理 API、演示文稿数据快照的结构定义以及渲染适配层如何把数据模型绘制到画布上并能直接基于 examples/src/slides/main.ts 写出可运行的 Slides 应用。一、包定位一个无 UI 的“核心模型包”根据官方 README 的 Package Overview 表格univerjs/slides具备以下包级属性PackageUMD globalCSSLocalesFacade entryuniverjs/slidesUniverSlidesNoNoNo从中可以得到三个关键定位无 CSS、无 Locales它不包含任何样式文件与多语言资源界面相关的样式与文案由univerjs/slides-ui等上层 UI 包提供无 Facade entry面向业务的高级 Facade API 不在本包中说明本包面向框架内部与插件开发而非最终业务调用层有 UMD 全局变量UniverSlides在以 UMD 方式如 examples/umd/sheets.html 类似的场景直接引入时可从全局拿到该命名空间。从源码入口 packages/slides/src/index.ts 看它对外导出的全部能力是DEFAULT_SLIDE默认幻灯片数据常量来自 basics/const/default-slide.tsIUniverSlidesConfig插件配置类型来自 config/config.tsSlideDataModel核心数据模型类来自>pnpm add univerjs/slides # or npm install univerjs/slides同时 README 强调了一个重要的工程约定Keep alluniverjs/*packages on the same version即所有univerjs/*包应保持同一版本。这一点在 monorepo 中尤为重要——本仓库使用 pnpm workspace 管理见 pnpm-workspace.yamlpackage.json 中univerjs/core与univerjs/engine-render均声明为workspace:*说明它们随仓库同步发布、版本号严格一致。如果混用不同版本可能因依赖解析不一致导致类型或运行时错误。三、插件注册UniverSlidesPluginREADME 给出最小用法import { UniverSlidesPlugin } from univerjs/slides; univer.registerPlugin(UniverSlidesPlugin);深入 plugin.ts 可以看到该插件的完整元信息与生命周期行为static pluginName UNIVER_SLIDES_PLUGIN插件唯一标识static packageName pkg.name、static version pkg.version绑定到当前包版本static type UniverInstanceType.UNIVER_SLIDE插件对应的单元类型为“幻灯片”类装饰器DependentOn(UniverRenderEnginePlugin)强依赖渲染引擎插件注册前必须已注册UniverRenderEnginePlugin否则无法启动——这从侧面印证了幻灯片本质上是“画布上的多页面场景”构造函数中通过merge({}, defaultPluginConfig, this._config)合并配置并写入IConfigService的slides.configSLIDES_PLUGIN_CONFIG_KEY键下供依赖注入体系读取onStarting()生命周期中调用this._univerInstanceService.registerCtorForType(UniverInstanceType.UNIVER_SLIDE, SlideDataModel)把SlideDataModel注册为 UNIVER_SLIDE 类型单元的构造器即之后调用univer.createUnit(UniverInstanceType.UNIVER_SLIDE, data)时框架会自动用SlideDataModel来封装传入的数据快照。配置接口IUniverSlidesConfig目前是空接口见 config/config.ts默认配置defaultPluginConfig {}注册插件时暂不需要传入任何配置项后续扩展能力将通过该接口演进。四、完整集成示例跑起一个 Slides 应用仅注册UniverSlidesPlugin还不够——它只提供核心模型。要看到真实渲染效果需要按 examples/src/slides/main.ts 的组合方式集成全套插件import { LocaleType, Univer, UniverInstanceType } from univerjs/core; import { UniverRenderEnginePlugin } from univerjs/engine-render; import { UniverSlidesPlugin } from univerjs/slides; import { UniverSlidesUIPlugin } from univerjs/slides-ui; import { UniverUIPlugin } from univerjs/ui; import { UniverDocsPlugin } from univerjs/docs; import { UniverDocsUIPlugin } from univerjs/docs-ui; import { DEFAULT_SLIDE_DATA } from univerjs/mockdata; import zhCN from univerjs/mockdata/locales/zh-CN; const univer new Univer({ locale: LocaleType.ZH_CN, locales: { [LocaleType.ZH_CN]: zhCN, }, }); // 核心渲染与 UI univer.registerPlugin(UniverRenderEnginePlugin); univer.registerPlugin(UniverUIPlugin, { container: app, ribbonType: grid, }); // 幻灯片核心 幻灯片 UI univer.registerPlugin(UniverSlidesPlugin); univer.registerPlugin(UniverSlidesUIPlugin); // 示例还组合了文档、公式、绘图、水印等能力 univer.registerPlugin(UniverDocsPlugin); univer.registerPlugin(UniverDocsUIPlugin); univer.registerPlugin(UniverFormulaEnginePlugin); univer.registerPlugin(UniverDrawingPlugin); univer.registerPlugin(UniverWatermarkPlugin); // 创建幻灯片单元 univer.createUnit(UniverInstanceType.UNIVER_SLIDE, DEFAULT_SLIDE_DATA);该示例中的DEFAULT_SLIDE_DATA来自 common/mockdata/src/slides/default-slide-data.ts是一个 960×540 画布、包含 7 个页面封面、目录、战略、技术、富文本、业务、无限的完整演示文稿快照页序由pageOrder数组决定export const DEFAULT_SLIDE_DATA: ISlideData { id: slide_test, title: UniverSlide, pageSize: { width: 960, height: 540 }, body: { pages: { cover_1: DEFAULT_FIRST_PAGE, catalog_1: DEFAULT_SECOND_PAGE, // ... }, pageOrder: [cover_1, catalog_1, strategic_1, technology_1, richText_1, business_1, unlimited_1], }, };五、核心数据模型SlideDataModelSlideDataModeldata-model/slide-data-model.ts继承自UnitModelISlideData, UniverInstanceType.UNIVER_SLIDE是幻灯片数据快照在内存中的响应式模型。其关键设计如下。5.1 状态与响应式用BehaviorSubjectNullableISlidePage维护当前激活页_activePage$对外暴露只读流activePage$用BehaviorSubjectstring维护标题_name$对外暴露name$构造函数将传入的PartialISlideData与DEFAULT_SLIDE合并{ ...DEFAULT_SLIDE, ...snapshot }因此缺失字段如pageSize会落到默认值 300×300见 basics/const/default-slide.ts。5.2 页面访问 API方法作用getPages()返回body.pages页面字典{ [id]: ISlidePage }getPageOrder()返回body.pageOrder页面顺序数组getPage(pageId)按 id 取单个页面getElementsByPage(pageId)取某页的全部页面元素getElement(pageId, elementId)取某页中的某个元素getPageSize()返回画布尺寸ISizegetBlankPage()生成一张空白页SLIDE 类型、zIndex10、白底、空元素表setActivePage(page)/getActivePage()设置/读取当前激活页updatePage(pageId, page)覆盖更新某页appendPage(page)追加新页到当前激活页之后插入pageOrder一个值得注意的细节getActivePage()在无激活页时自动回退到pageOrder的第一页这保证了多页演示文稿在初始状态即有“当前页”。5.3 关于协同编辑的现状getRev()恒返回0incrementRev()/setRev()为空操作源码注释明确写道 slide has not implement collaborative editing yetTODOjikkai。也就是说当前版本下幻灯片单元尚未接入协同编辑的版本管理这一点与已支持协同的 Sheets/Docs 有所区别接入方不应依赖 rev 机制。六、数据快照结构页面与元素模型6.1ISlideData整份演示文稿定义见 types/interfaces/i-slide-data.tsexport interface ISlideData extends IReferenceSource { id: string; // unit id locale?: LocaleType; title: string; pageSize: ISize; // 画布尺寸如 960×540 body?: ISlidePageBody; }IReferenceSource还支持可选的主母版master、讲义母版handoutMaster、备注母版notesMaster、版式layouts与列表lists这套命名与 Google Slides API 的母版/版式体系对齐。body中pages是页面字典pageOrder是页面顺序数组——顺序与内容分离便于调整页序。6.2ISlidePage单页export interface ISlidePage { id: string; pageType: PageType; // SLIDE / MASTER / LAYOUT / HANDOUT_MASTER / NOTES_MASTER zIndex: number; title: string; description: string; pageBackgroundFill: IColorStyle; // 页面背景色 colorScheme?: ThemeColorType; pageElements: { [elementId: string]: IPageElement }; slideProperties?: ISlideProperties; // 引用 layoutObjectId / masterObjectId可标记 isSkipped layoutProperties?: ILayoutProperties; notesProperties?: INotesProperties; handoutProperties?: IHandoutProperties; masterProperties?: IMasterProperties; }pageType区分普通幻灯片页与母版/版式/讲义/备注母版其中ISlideProperties记录页面对应版式与母版的引用并可设置isSkipped跳过放映。6.3IPageElement页面元素页面元素是幻灯片的核心构成单元支持多种类型export enum PageElementType { SHAPE, // 形状 IMAGE, // 图片 TEXT, // 富文本 SPREADSHEET, // 电子表格内嵌 worksheet 数据 DOCUMENT, // 文档IDocumentData SLIDE, // 嵌套幻灯片ISlideData可实现“画中画” }元素基座包含统一变换属性left / top / width / height / angle / scaleX / scaleY / skewX / skewY / flipX / flipY与zIndex、title、description随后通过 union 字段承载具体类型的数据shape?: IShape——由ShapeType指定预设几何类型如rect、ellipse、star5、heart等见 prst-geom-type.ts并附带shapeProperties、placeholder与linkimage?: IImage——imageProperties含IImageProperties与可选占位符、链接richText?: ISlideRichTextProps——既支持纯文本text也支持完整的富文本文档rich: IDocumentDataspreadsheet?: { worksheet, styles }——把一张工作表连同样式表嵌入幻灯片document?: IDocumentData——嵌入文档slide?: ISlideData——嵌套幻灯片对应SlideAdaptor的递归渲染能力customBlock?: ICustomBlock——插件自定义块。IShape/IImage上的link使用RelativeSlideLink枚举表达相对跳转目标NEXT_SLIDE下一张、PREVIOUS_SLIDE上一张、FIRST_SLIDE第一张、LAST_SLIDE最后一张或指定具体pageId/slideIndex。6.4 形状体系ShapeTypeprst-geom-type.ts 按 OOXML 规范 20.1.9.18prstGeom预设几何组织形状枚举BasicShapesline、triangle、rect、diamond、parallelogram、pentagon、hexagon、star4star32、roundRect、ellipse 等ArrowsAndMarkersShapesrightArrow、leftArrow、upDownArrow、chevron、circularArrow 等箭头与标记OtherShapesplaque、can、cube、donut、noSmoking、blockArc、foldedCorner 等SpecialShapessmileyFace、heart、lightningBolt、sun、moon、cloud、pie、teardrop、各类 callout 与 actionButton 等。ShapeType是四类枚举的联合PresetGeometryType ShapeType | custom额外允许自定义几何。七、渲染适配层从数据到画布univerjs/slides通过 views/render 下的适配器把ISlideData渲染到univerjs/engine-render的画布场景中。7.1SlideAdaptor页面场景构建views/render/adaptors/slide-adaptor.ts 中的SlideAdaptor extends ObjectAdaptorzIndex 6viewKey PageElementType.SLIDE通过CanvasObjectProviderRegistry.add(new SlideAdaptorFactory())注册到全局对象提供器注册表convert()方法当页面元素类型为SLIDE时用元素内的slide: ISlideData构造新的SlideDataModel创建Slide渲染组件并启用导航enableNav()与选中裁剪enableSelectedClipElement()按pageOrder顺序为每一页创建独立Scene页内用Viewport承载、closeClip()关闭裁剪把pageElements交给ObjectProvider批量转换为渲染对象再叠加背景矩形_addBackgroundRect默认白底灰边最后activeFirstPage()激活第一页每个页面对象都会attachTransformerTo挂接变换器支持选中与拖动变换。7.2 元素适配器族views/render/adaptors 同时导出了六类元素适配器SlideAdaptor嵌套幻灯片、DocsAdaptor文档、ImageAdaptor图片、RichTextAdaptor富文本、ShapeAdaptor形状、SpreadsheetAdaptor表格对应PageElementType的六个枚举值形成“元素类型 → 渲染对象”的映射管线。此外 views/render/index.ts 定义了渲染场景的键约定SLIDE_KEY.COMPONENT __slideRender__、SCENE __mainScene__、VIEW __mainView__供 UI 层univerjs/slides-ui定位画布组件。八、测试佐证模型行为即契约data-model/tests/slide-data-model.spec.ts 用 vitest 固化了SlideDataModel的行为契约可作为接入方编写代码时的参考基准页面管理构造含两页的快照后getPages()/getPageOrder()/getPage()/getElementsByPage()/getElement()的取值符合预期激活页流订阅activePage$后调用setActivePage()会推送新激活页未显式设置时getActivePage()回退到第一页空白页getBlankPage()返回PageType.SLIDE、zIndex: 10、白底页面追加/更新appendPage()将新页插入当前激活页之后updatePage()覆盖更新页面内容版本号incrementRev()/setRev(5)后getRev()仍为0印证协同编辑未实现空快照稳定性不含body的空快照调用页面 API 不会抛错getPages()/getPageOrder()返回undefined模型保持稳定。运行测试pnpm --filter univerjs/slides test对应 package.json 中的vitest run。九、小结univerjs/slides是 Univer 演示文稿能力的“引擎舱”它不提供按钮和弹窗但定义了整份演示文稿的数据快照结构ISlideData→ISlidePage→IPageElement、响应式数据模型SlideDataModel与画布渲染适配管线SlideAdaptor 六类元素适配器。接入方只需按 README 安装并保持univerjs/*同版本注册UniverSlidesPlugin配合UniverRenderEnginePlugin参考 examples/src/slides/main.ts 组合 UI 层插件传入一份符合ISlideData的快照可直接复用 common/mockdata 的DEFAULT_SLIDE_DATA调用univer.createUnit(UniverInstanceType.UNIVER_SLIDE, data)。至此一套可渲染、可交互翻页、选中、变换的演示文稿应用即可运行起来并可通过SlideDataModel的 API 在运行时增删页、切换激活页、修改页面元素。【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考