Web SDK

Пользовательские компоненты

Web SDK предлагает несколько способов интеграции пользовательских компонентов, позволяя расширять и настраивать его функциональность. В этом руководстве рассмотрены несколько распространённых способов.

Univer не передаёт компоненты напрямую в качестве параметров функций рендеринга. Чтобы использовать компоненты в различных точках монтирования, сначала зарегистрируйте их в Univer через Facade API.

Если вы не знаете, как получить экземпляр Facade API, обратитесь к разделу Facade API.

Регистрация пользовательских компонентов

TypeScript
univerAPI.registerComponent(componentKey, CustomComponent, options)

Для регистрации пользовательских компонентов используйте метод univerAPI.registerComponent. Он принимает три параметра:

  • componentKey: уникальный идентификатор компонента, по которому к нему можно обращаться в Univer.
  • CustomComponent: реализация компонента — это может быть компонент React, Vue или Web Component.
  • 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, установите и зарегистрируйте плагин UniverVue3AdapterPlugin из пакета @univerjs/ui-adapter-vue3:

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 прекращена (EOL) и эта версия больше не сопровождается, сейчас Univer не предоставляет для нее плагин 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)

При регистрации компонентов Vue 2.x необходимо задать для параметра 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, а затем установите и зарегистрируйте плагин UniverWebComponentAdapterPlugin из пакета @univerjs/ui-adapter-web-component:

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',})

Angular

Преобразуйте компонент Angular в пользовательский элемент через createCustomElement из @angular/elements, затем зарегистрируйте его через адаптер Web Component в Univer. Компонент можно использовать в боковой панели или диалоге.

Добавьте @angular/elements той же версии, что и @angular/core, и @univerjs/ui-adapter-web-component той же версии, что и остальные пакеты Univer.

Вызовите эту функцию после инициализации Univer. В компоненте-хозяине получите Angular-инжектор через private readonly injector = inject(Injector) и вызовите registerAngularPanel(univer, univerAPI, this.injector). Импортируйте inject и Injector из @angular/core в этом компоненте.

TypeScript
import type { Injector } from '@angular/core'import type { FUniver, Univer } from '@univerjs/presets'import { Component } from '@angular/core'import { createCustomElement } from '@angular/elements'import { UniverWebComponentAdapterPlugin } from '@univerjs/ui-adapter-web-component'@Component({  selector: 'app-angular-panel',  standalone: true,  template: '<p>Hello from Angular!</p>',})export class AngularPanelComponent {}export function registerAngularPanel(univer: Univer, univerAPI: FUniver, injector: Injector) {  const element = createCustomElement(AngularPanelComponent, { injector })  univer.registerPlugin(UniverWebComponentAdapterPlugin)  return univerAPI.registerComponent('univer-angular-panel', element, {    framework: 'web-component',  })}

После отрисовки редактора используйте зарегистрированный ключ как содержимое боковой панели:

TypeScript
const sidebar = univerAPI.openSidebar({  header: { title: 'Angular' },  children: { label: 'univer-angular-panel' },  width: 360,})

Сохраните дескрипторы регистрации и боковой панели и вызовите их методы dispose(), когда они больше не нужны. Регистрируйте элемент один раз на приложение. Имя должно содержать дефис и отличаться от selector компонента Angular.

Angular Elements преобразует входы в свойства элемента, а выходы — в события DOM CustomEvent. Адаптер Univer передаёт свойства, но не подписывается автоматически на выходы Angular: подключите нужные события явно.

Использование пользовательских компонентов

С помощью следующих методов можно гибко интегрировать в Univer различные пользовательские компоненты, расширяя и настраивая его возможности.

Внимание

  1. Перед использованием этих методов убедитесь, что Univer завершил отрисовку. 2. Если компонент требуется зарегистрировать, перед использованием убедитесь, что регистрация выполнена правильно. 3. Используйте метод dispose(), чтобы очищать и удалять добавленные компоненты и тем самым избегать утечек памяти.

Добавление пользовательских пунктов меню

Пользовательские компоненты можно добавлять как на верхнюю панель меню (Ribbon), так и в контекстное меню (Context Menu). Для этого создайте пользовательский плагин.

Замена встроенных компонентов

Предупреждение

Замена встроенных компонентов может нарушить работу некоторых функций. Прежде чем заменять компоненты, внимательно изучите исходный код и документацию и действуйте осторожно.

univerAPI.registerComponent по умолчанию регистрирует переопределение (override: true). Оно имеет приоритет независимо от порядка регистрации стандартного компонента плагином. Для каждого componentKey допустимо только одно активное переопределение; перед повторной регистрацией освободите предыдущее. Метод dispose() возвращённого объекта восстанавливает стандартный компонент, если он зарегистрирован. Параметр { override: false } регистрирует стандартный компонент.

Регистрируйте переопределение до первого открытия представления. Изменение регистрации не перерисовывает уже смонтированные представления автоматически.

Например, встроенный компонент ColorPicker можно заменить следующим образом:

TSX
// Following code only replaces the UI of the built-in ColorPicker component, not its functionalityuniverAPI.registerComponent('UI_COLOR_PICKER_COMPONENT', () => <input type="color" />)

Использование в качестве компонентов содержимого

На боковой панели

Метод univerAPI.openSidebar позволяет открыть в интерфейсе Univer боковую панель с пользовательским компонентом.

TSX
// You should register the component at an appropriate time (e.g., after Univer has loaded)univerAPI.registerComponent('MyCustomSidebarComponent', () => <div>Hello Univer!</div>)const sidebar = univerAPI.openSidebar({  header: { title: 'My Sidebar' },  children: { label: 'MyCustomSidebarComponent' },  onClose: () => {    console.log('close')  },  width: 360,})// Later close the sidebarsidebar.dispose()

Справочник: univerAPI.openSidebar

В диалоговом окне

Метод univerAPI.openDialog позволяет открыть диалоговое окно с пользовательским компонентом.

TSX
// You should register the component at an appropriate time (e.g., after Univer has loaded)univerAPI.registerComponent('MyCustomDialogComponent', () => <div>Hello Univer!</div>)const dialog = univerAPI.openDialog({  id: 'unique-dialog-id', // The unique identifier for the dialog  draggable: true,  width: 300,  title: { title: 'My Dialog' },  children: {    label: 'MyCustomDialogComponent',  },  destroyOnClose: true,  preservePositionOnDestroy: true,  onClose: () => {},})// Later close the dialogdialog.dispose()

Справочник: univerAPI.openDialog

Насколько полезно это руководство?

© 2026 DreamNum Co., Ltd.