自定义组件

Web SDK 提供了多种方式来集成自定义组件,使你能够扩展和定制 Web SDK 的功能。本指南将介绍几种常用的方法。

Univer 并不会直接将组件作为参数传递给任何渲染函数,你需要通过 Facade API 将组件注册到 Univer 中之后,才能在各个挂载点使用它们。

如果你还不了解如何获取 Facade API 的实例,可以参考 Facade API

注册自定义组件

TypeScript
univerAPI.registerComponent(componentKey, CustomComponent, options)

使用 univerAPI.registerComponent 方法来注册自定义组件。这个方法接受三个参数:

  • componentKey: 组件的唯一标识符,用于在 Univer 中引用该组件。
  • CustomComponent: 组件的实现,可以是 React、Vue 或 Web Components。
  • options: 可选的配置选项,可用于指定组件所依赖的框架或其他相关设置。

React 组件

注册 React 组件无需额外的配置,只需确保组件是一个有效的 React 组件即可。以下是一个简单的示例:

TSX
function ReactComponent(props: Record<string, any>) {  return <div>Hello Univer!</div>}univerAPI.registerComponent('MyReactComponent', ReactComponent)

Vue 组件

Vue 3.x

注册 Vue 组件时,需要确保安装并注册 @univerjs/ui-adapter-vue3UniverVue3AdapterPlugin 插件:

Shell
pnpm add @univerjs/ui-adapter-vue3
TypeScript
import { UniverVue3AdapterPlugin } from '@univerjs/ui-adapter-vue3'univer.registerPlugin(UniverVue3AdapterPlugin)

注册 Vue 组件时,需要指定 framework 选项为 'vue3'

TSX
const Vue3Component = defineComponent({  setup(props) {    return () => <div>Hello Univer!</div>  },})univerAPI.registerComponent('MyVue3Component', Vue3Component, {  framework: 'vue3',})

Vue 2.x

由于 Vue 2.x 已经不再维护,Univer 暂时没有提供 Vue 2.x 的 UI 适配器插件的计划,你可以参考如下代码通过自定义插件来实现一个 Vue 2.x 的适配器:

TypeScript
import { DependentOn, Inject, Injector, Plugin } from '@univerjs/core'import { ComponentManager, UniverUIPlugin } from '@univerjs/ui'import Vue from 'vue'/** * The plugin that allows Univer to use Vue 2 components as UI components. */@DependentOn(UniverUIPlugin)export class UniverVue2AdapterPlugin extends Plugin {  static override pluginName = 'UNIVER_UI_VUE2_ADAPTER_PLUGIN'  constructor(    private readonly _config = {},    @Inject(Injector) protected readonly _injector: Injector,    @Inject(ComponentManager) protected readonly _componentManager: ComponentManager,  ) {    super()  }  override onStarting(): void {    const { createElement, useEffect, useRef } = this._componentManager.reactUtils    this._componentManager.setHandler('vue2', (component: any) => {      return (props: Record<string, any>) =>        createElement(VueComponentWrapper, {          component,          props: Object.keys(props).reduce<Record<string, any>>((acc, key) => {            if (key !== 'key') {              acc[key] = props[key]            }            return acc          }, {}),          reactUtils: { createElement, useEffect, useRef },        })    })  }}export function VueComponentWrapper(options: {  component: any  props: Record<string, any>  reactUtils: typeof ComponentManager.prototype.reactUtils}) {  const { component, props, reactUtils } = options  const { createElement, useEffect, useRef } = reactUtils  const domRef = useRef<HTMLDivElement>(null)  useEffect(() => {    if (!domRef.current) return    const Constructor = Vue.extend(component)    const instance = new Constructor({      data: props,    })    instance.$mount()    domRef.current.appendChild(instance.$el)    return () => {      instance.$destroy()    }  }, [props])  return createElement('div', { ref: domRef })}

然后将其注册:

TypeScript
import { UniverVue2AdapterPlugin } from './ui-adapter-vue2'univer.registerPlugin(UniverUIPlugin)univer.registerPlugin(UniverVue2AdapterPlugin)

使用时需要指定 framework 选项为 'vue2'

TSX
const Vue2Component = Vue.component('MyVue2Component', {  template: '<div>Hello, Univer!</div>',})univerAPI.registerComponent('MyVue2Component', Vue2Component, {  framework: 'vue2',})

Web Components

注册 Web Components 时,需要确保组件符合 Web Components 标准,并安装和注册 @univerjs/ui-adapter-web-componentUniverWebComponentAdapterPlugin 插件:

Shell
pnpm add @univerjs/ui-adapter-web-component
TypeScript
import { UniverWebComponentAdapterPlugin } from '@univerjs/ui-adapter-web-component'univer.registerPlugin(UniverWebComponentAdapterPlugin)

注册 Web Components 时,需要指定 framework 选项为 'web-component'

TSX
class WebComponent extends HTMLElement {  constructor() {    super()    const shadow = this.attachShadow({ mode: 'open' })    const div = document.createElement('div')    div.textContent = 'Hello Univer!'    shadow.appendChild(div)  }}univerAPI.registerComponent('my-web-component', WebComponent, {  framework: 'web-component',})

使用自定义组件

通过以下方法,你可以灵活地在 Univer 中集成各种自定义组件,从而增强和定制 Univer 的功能。

注意事项

  1. 在使用这些方法时,请确保Univer已经完成渲染。 2. 对于需要注册的组件,请确保在使用前已正确注册。 3. 使用 dispose() 方法来清理和移除添加的组件,以避免内存泄漏。

添加自定义菜单项

顶部菜单栏(Ribbon)和右键菜单(Context Menu)都可以添加自定义组件。请从自己的插件中提供这些菜单项,在使用前注册组件,并随插件一起释放相关注册。

替换内置组件

警告

替换内置组件可能会导致一些功能无法正常工作,请在充分阅读源码和文档后自行寻找可替换的组件并谨慎操作。

通过 univerAPI.registerComponent 方法注册组件时,如果传入的 componentKey 已经存在,那么 Univer 会将其替换为新的组件。

例如简单地替换内置的 ColorPicker 组件:

TSX
// 此代码仅可在 UI 层面替换内置 ColorPicker 组件,无法替代其功能实现univerAPI.registerComponent('UI_COLOR_PICKER_COMPONENT', () => <input type="color" />)

作为内容组件添加到……

在侧边栏中使用

使用 univerAPI.openSidebar 方法可以在Univer界面中打开一个包含自定义组件的侧边栏。

TSX
// 你应该在合适的时机(比如渲染完成)注册组件univerAPI.registerComponent('MyCustomSidebarComponent', () => <div>Hello Univer!</div>)const sidebar = univerAPI.openSidebar({  header: { title: 'My Sidebar' },  children: { label: 'MyCustomSidebarComponent' },  onClose: () => {    console.log('close')  },  width: 360,})// 稍后关闭侧边栏sidebar.dispose()

参考: univerAPI.openSidebar

在对话框中使用

使用 univerAPI.openDialog 方法可以打开一个包含自定义组件的对话框。

TSX
// 你应该在合适的时机(比如渲染完成)注册组件univerAPI.registerComponent('MyCustomDialogComponent', () => <div>Hello Univer!</div>)const dialog = univerAPI.openDialog({  id: 'unique-dialog-id', // 对话框的唯一标识符  draggable: true,  width: 300,  title: { title: 'My Dialog' },  children: {    label: 'MyCustomDialogComponent',  },  destroyOnClose: true,  preservePositionOnDestroy: true,  onClose: () => {},})// 稍后关闭对话框dialog.dispose()

参考: univerAPI.openDialog

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.