ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用 @univerjs/ui-adapter-web-component 将 Univer UI 接入 Web Components 生态

使用 @univerjs/ui-adapter-web-component 将 Univer UI 接入 Web Components 生态 使用 univerjs/ui-adapter-web-component 将 Univer UI 接入 Web Components 生态【免费下载链接】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导读univerjs/ui-adapter-web-component是 Univer 官方提供的 UI 适配器插件它让 Univer 的 UI 服务可以直接把Web Components自定义元素当作 UI 组件来注册与渲染从而摆脱对特定框架组件的强绑定。本文以该包的 README 为骨架结合仓库源码讲解包的安装、插件注册、web-componentframework 的用法、运行时 props 以 DOM 属性传递的机制以及底层ComponentManager与包装组件的实现原理并给出一个完整的 Lit 自定义元素集成示例帮助你掌握在非 React 技术栈中扩展 Univer UI 的实战方案。包概览定位与产物该包在仓库中以 monorepo workspace 方式维护对应目录为 packages/ui-adapter-web-component包的元信息见 package.json项值包名univerjs/ui-adapter-web-componentUMD 全局变量UniverUiAdapterWebComponentCSS无不内置样式Locales无不内置多语言资源Facade 入口无从表格可以看出这个包是纯逻辑适配层不携带样式、不携带语言包、不扩展 Facade API职责单一——为ComponentManager提供一个能把自定义元素渲染进 Univer UI 的 framework 处理器。包本身只依赖univerjs/core与univerjs/ui两个核心包见 package.json 的 dependencies 字段。仓库当前版本为1.0.0-beta.2与整个univerjs/*系列保持一致。安装使用你习惯的包管理器安装pnpm add univerjs/ui-adapter-web-component # or npm install univerjs/ui-adapter-web-component需要注意Univer 所有univerjs/*包必须保持在同一版本否则可能出现依赖不兼容导致的运行时错误。这也是 monorepo 工作区workspace:*依赖在发布后的使用约束。快速开始注册适配器插件安装完成后在初始化Univer实例时注册插件即可import { UniverWebComponentAdapterPlugin } from univerjs/ui-adapter-web-component; univer.registerPlugin(UniverWebComponentAdapterPlugin);插件类UniverWebComponentAdapterPlugin定义于 plugin.ts插件名称为UNIVER_UI_ADAPTER_WEB_COMPONENT_PLUGIN包名与版本号分别取自pkg.name与pkg.version构造时通过merge({}, defaultPluginConfig, this._config)合并用户配置并以UI_ADAPTER_WEB_COMPONENT_PLUGIN_CONFIG_KEY值为ui-adapter-web-component.config见 config.ts写入IConfigService。当前版本的IUniverWebComponentAdapterConfig是空接口、defaultPluginConfig为空对象意味着该插件目前无需任何必填配置后续版本可平滑扩展。核心用法以web-componentframework 注册自定义元素注册插件之后就可以通过Facade API的univerAPI.registerComponent注册自定义元素并通过framework: web-component选项声明该组件是一个 Web Componentclass MyPopup extends HTMLElement { set data(value) { this.textContent value?.label ?? ; } } univerAPI.registerComponent(my-popup, MyPopup, { framework: web-component });这里的要点MyPopup是一个标准的自定义元素类继承HTMLElement而不是 React/Vue 组件registerComponent的第一个参数my-popup既是组件在ComponentManager中的注册名也会被用作自定义元素的标签名custom element name按规范必须包含连字符运行时 props 会被直接赋值到创建出的 DOM 元素上作为 DOM 属性DOM property传递因此支持对象类型的值例如示例中的data可以是{ label: string }这类对象以及extraProps。这正是它与 React props 传递方式的关键区别——你通过自定义元素类上的set data(value)访问器接收数据。Facade 方法如何落到ComponentManageruniverAPI.registerComponent是FUniver的 UI Mixin 方法见 f-univer.tsoverride registerComponent(name: string, component: any, options?: IComponentOptions): IDisposable { const componentManager this._injector.get(ComponentManager); return this.disposeWithMe(componentManager.register(name, component, options)); }它最终调用ComponentManager.register。在 component-manager.ts 中register的默认 framework 是reactregister(name: string, component: ComponentType, options?: IComponentOptions): IDisposable { const { framework react } options || {}; if (framework vue3 !this._handler.vue3) { throw new Error([ComponentManager] Vue3 support is no longer built-in since v0.9.0, please install univerjs/ui-adapter-vue3 plugin.); } // ... this._components.set(name, { framework, component }); }注册后任何使用该组件名的 UI 场景弹窗、侧边栏、通知等在渲染时都会调用ComponentManager.get(name)根据framework找到对应的 handler 进行适配。若找不到 handler会抛出[ComponentManager] No handler found for framework: ...错误——这也是必须注册本适配器插件的原因。原理剖析插件如何把自定义元素桥接到 React 渲染Univer 的 UI 层基于 React 构建而 Web Components 原生不参与 React 的虚拟 DOM。适配器在onStarting生命周期中为ComponentManager注入web-component处理器代码位于 plugin.tsoverride onStarting(): void { const { createElement, useEffect, useRef } this._componentManager.reactUtils; this._componentManager.setHandler(web-component, (component, name) { return (props) createElement(WebComponentComponentWrapper, { component, props: { name, componentProps: props, }, reactUtils: { createElement, useEffect, useRef }, }); }); }随后WebComponentComponentWrapper承担具体的桥接工作同一文件内其核心逻辑校验与注册要求必须提供name否则抛出WebComponentComponentWrapper requires a name prop to define the custom element.若customElements.get(name)不存在则调用customElements.define(name, component)完成自定义元素注册懒注册、去重创建并注入 props在useEffect中通过document.createElement(name)创建元素遍历componentProps把每个键值对直接赋值为元素的 DOM 属性webComponentWithProps[key] value并跳过key字段挂载与清理把创建出的元素appendChild到useRef指向的容器div中并在 effect 清理函数中removeChild实现组件卸载时的 DOM 回收effect 依赖componentPropsprops 变化会重新创建并挂载元素。因此整个链路是React 渲染容器 →WebComponentComponentWrapper→ 原生自定义元素。Univer 的 UI 服务弹窗、消息、侧边栏等无需改动即可渲染任意 Web Components。reactUtilscreateElement/useEffect/useRef来自 component-manager.ts 中ComponentManager.reactUtils字段它把 React 的最小渲染原语以依赖注入方式提供给适配层使本包无需直接 import React 也能完成桥接。实战用 Lit 自定义元素承载整个 Univer 实例仓库的 examples/src/sheets-webcomponent/main.tsx 给出了一个完整的端到端示例把整个 Univer 工作表封装成一个自定义元素my-univer并在其中注册 Web Component 适配器插件。核心步骤customElement(my-univer) class MyWebComponent extends LitElement { override firstUpdated() { const container this.renderRoot.querySelector(#containerId) as HTMLDivElement; const univer new Univer({ locale: LocaleType.ZH_CN, locales: { [LocaleType.ZH_CN]: zhCN }, logLevel: LogLevel.VERBOSE, }); // 基础插件网络、公式引擎、渲染引擎、UI 插件容器指向 Web Component 内部 div univer.registerPlugin(UniverNetworkPlugin); univer.registerPlugin(UniverFormulaEnginePlugin); univer.registerPlugin(UniverRenderEnginePlugin); univer.registerPlugin(UniverUIPlugin, { container, ribbonType: classic, }); // ... 文档 / 表格 / 各功能插件 ... // 适配器插件让 Univer UI 服务支持 Web Components 组件 univer.registerPlugin(UniverWebComponentAdapterPlugin); univer.createUnit(UniverInstanceType.UNIVER_SHEET, DEFAULT_WORKBOOK_DATA_DEMO); window.univerAPI FUniver.newAPI(univer); } override render() { return html link relstylesheet href./main.css div styleheight: 100%; idcontainerId / ; } }要点解读用univerjs/ui的UniverUIPlugin的container配置把 Univer 渲染进 Web Component 的 shadow/render root 内的#containerId容器适配器插件与UniverVue3AdapterPlugin并列注册说明 Univer 的组件框架体系是可叠加的React 为默认、Vue3 与 Web Components 通过各自 adapter 插件扩展互不冲突示例还演示了lit/react的createComponent反向用法——把 Lit 自定义元素封装成 React 组件以便在 React 宿主中挂载适合从 React 项目平滑引入 Web Components。使用建议与注意事项组件名即标签名registerComponent的名字必须是合法的自定义元素名含连字符如my-popup并且最终通过customElements.define注册到全局 registry注意避免与页面中已有元素重名重名时customElements.define会抛错适配器已用customElements.get做了去重保护数据传递走 DOM 属性props 以属性而非 HTML attribute 的方式赋值所以可以传递对象、函数等复杂值但这也意味着自定义元素需要通过set xxx(value)访问器主动接收并自行处理渲染如示例中把data.label写入textContent生命周期由 React 驱动元素创建、挂载、卸载完全由WebComponentComponentWrapper的 effect 管理自定义元素本身遵循标准 Web Components 生命周期二者通过 DOM 边界解耦包体积友好本包不携带 CSS 与 locales不引入额外 UI 资源适合按需集成。总结univerjs/ui-adapter-web-component通过一个轻量的插件 包装组件把 Univer 的ComponentManager组件体系扩展到 Web Components 生态。无论是为现有 Univer 应用接入自定义弹窗、消息通知还是把整个 Univer 实例封装成可与任意框架共存的自定义元素它都提供了标准、可复用的桥接方案。配合 plugin.ts、component-manager.ts 与 main.tsx 三个文件即可完整掌握从注册、适配到端到端集成的全部链路。【免费下载链接】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),仅供参考
返回列表