自訂元件

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-vue3 的 UniverVue3AdapterPlugin 插件:

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'/** * 允許 Univer 使用 Vue 2 元件作為 UI 元件的插件。 */@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-component 的 UniverWebComponentAdapterPlugin 插件:

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 預設註冊覆寫元件(override: true)。無論外掛在呼叫前或呼叫後註冊內建預設元件,覆寫元件都優先生效。每個 componentKey 同時只能有一個覆寫元件,再次註冊前須先釋放上一個註冊。呼叫回傳值的 dispose() 後,會恢復已註冊的內建預設元件。傳入 { override: false } 則註冊預設元件。

請在對應檢視首次開啟前註冊覆寫元件;變更註冊不會自動重新呈現已掛載的檢視。

例如簡單地替換內建的 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.