Componentes personalizados

Web SDK ofrece varias formas de integrar componentes personalizados para ampliar y adaptar sus funciones. Esta guía presenta los métodos más habituales.

Univer no pasa directamente componentes como parámetros a ninguna función de renderizado. Debe registrar los componentes con Univer a través de la API de Facade antes de poder usarlos en varios puntos de montaje.

Si no está familiarizado con cómo obtener una instancia de la API de Facade, puede consultar API de Facade.

Registro de componentes personalizados

TypeScript
univerAPI.registerComponent(componentKey, CustomComponent, options)

Utilice el método univerAPI.registerComponent para registrar componentes personalizados. Este método acepta tres parámetros:

  • componentKey: un identificador único para el componente, usado para hacer referencia a él dentro de Univer.
  • CustomComponent: la implementación del componente, que puede ser un componente React, Vue o Web.
  • options: opciones de configuración opcionales que se pueden usar para especificar el marco del que depende el componente u otros relacionados settings.

Componentes de React

Para registrar un componente de React, no se requiere configuración adicional; solo asegúrese de que el componente sea un componente de React válido. Aquí hay un ejemplo simple:

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

Componentes de Vue

Vue 3.x

Si desea registrar componentes de Vue, asegúrese de instalar y registrar UniverVue3AdapterPlugin del paquete @univerjs/ui-adapter-vue3:

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

Al registrar componentes de Vue, debe especificar la opción framework como 'vue3':

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

Vue 2.x

Dado que Vue 2.x está en EOL (fin de vida útil) y ya no se mantiene, Univer actualmente no proporciona un complemento de adaptador de interfaz de usuario para Vue 2.x. Sin embargo, puede implementar un adaptador Vue 2.x creando un complemento personalizado. A continuación se muestra un ejemplo de cómo crear un complemento de adaptador 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 })}

Luego regístrelo:

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

Al registrar componentes Vue 2.x, debe especificar la opción framework como 'vue2':

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

Componentes web

Si desea registrar componentes web, asegúrese de que el componente se adhiera a los componentes web estándar e instale y registre UniverWebComponentAdapterPlugin del paquete @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)

Al registrar componentes web, debe especificar la opción framework como '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

Convierte un componente Angular en un elemento personalizado con createCustomElement de @angular/elements y regístralo con el adaptador Web Component de Univer. Así podrás usarlo en una barra lateral o un diálogo.

Añade @angular/elements con la misma versión que @angular/core, y @univerjs/ui-adapter-web-component con la misma versión que los demás paquetes Univer.

Llama a esta función después de inicializar Univer. En el componente anfitrión, obtén el inyector con private readonly injector = inject(Injector) y llama a registerAngularPanel(univer, univerAPI, this.injector). Importa inject e Injector desde @angular/core en ese componente.

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

Cuando el editor se haya renderizado, usa la clave registrada como contenido de la barra lateral:

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

Conserva los identificadores de registro y de la barra lateral, y llama a sus métodos dispose() cuando ya no los necesites. Registra el elemento una sola vez por aplicación. Su nombre debe contener un guion y ser distinto del selector Angular.

Angular Elements convierte las entradas en propiedades y las salidas en eventos DOM CustomEvent. El adaptador de Univer transmite propiedades, pero no se suscribe automáticamente a las salidas Angular; conecta explícitamente los eventos necesarios.

Usar componentes personalizados

Los siguientes métodos le permiten integrar de manera flexible varios componentes personalizados en Univer, mejorando y personalizando su funcionalidad.

Caution

  1. Asegúrese de que Univer haya completado el procesamiento antes de usar estos métodos. 2. Para los componentes que deben registrarse, asegúrese de que estén registrados correctamente antes de su uso. 3. Utilice el método dispose() para limpiar y eliminar componentes agregados para evitar pérdidas de memoria.

Agregar elementos de menú personalizados

La barra de menú superior (cinta) y el menú contextual (menú contextual) pueden incluir componentes personalizados. Para agregar componentes personalizados a los elementos del menú, debe crear un complemento personalizado. Hemos preparado una práctica recomendada para agregar elementos de menú personalizados para ayudarle a comenzar rápidamente.

Reemplazo de componentes integrados

Warning

Reemplazar componentes integrados puede provocar que algunas funcionalidades no funcionen correctamente. Lea detenidamente el código fuente y la documentación antes de intentar reemplazar componentes y proceda con precaución.

univerAPI.registerComponent registra una sustitución de forma predeterminada (override: true). Tiene prioridad independientemente de cuándo registre el plugin su componente predeterminado. Solo puede haber una sustitución activa por componentKey; libere el registro anterior antes de añadir otra. El método dispose() del objeto devuelto restaura el componente predeterminado, si está registrado. Use { override: false } para registrar un componente predeterminado.

Registre la sustitución antes de abrir la vista por primera vez. Cambiar el registro no vuelve a renderizar automáticamente las vistas ya montadas.

Las entradas públicas de los paquetes Sheets exportan estas claves para sustituir los componentes integrados correspondientes:

ComponenteClave exportadaPaquete
Nombres definidosDEFINED_NAME_CONTAINER@univerjs/sheets-ui
Más funcionesMORE_FUNCTIONS_COMPONENT@univerjs/sheets-formula-ui
Validación de datosDATA_VALIDATION_PANEL@univerjs/sheets-data-validation-ui
Formato condicionalCF_PANEL_KEY@univerjs/sheets-conditional-formatting-ui

Por ejemplo, para simplemente reemplazar el componente ColorPicker integrado:

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

Usar como componentes de contenido

En el Barra lateral

Usando el método univerAPI.openSidebar, puede abrir una barra lateral en la interfaz de Univer que contiene un componente personalizado.

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()

Referencia: univerAPI.openSidebar

Usando el método univerAPI.openDialog, puede abrir un cuadro de diálogo que contiene un componente personalizado.

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()

Referencia: univerAPI.openDialog

Adjuntar ventana emergente a celdas

Utilizando el método FRange.attachPopup, puede adjuntar una ventana emergente personalizada a un rango de celdas específico.

  • Una ventana emergente es un elemento DOM temporal adjunto a una celda, que generalmente se usa para mostrar información de estado transitorio y no admite almacenamiento persistente.
  • Puede usar el método FRange.attachPopup(popup: IFCanvasPopup) para adjuntar una ventana emergente personalizada a un rango de celdas específico.
  • La ventana emergente se adjuntará a los bordes de la celda y ajustará automáticamente su posición y orientación si obstruido.
TSX
// You should register the component at an appropriate time (e.g., after Univer has loaded)univerAPI.registerComponent('MyCustomPopupComponent', () => <div>Hello Univer!</div>)const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()const fRange = fWorksheet.getRange('A1:J10')// Attach the popup to the first cell of the range// If `disposable` is null, it indicates that the popup was not added successfullyconst disposable = fRange.attachPopup({  componentKey: 'MyCustomPopupComponent',})// Remove the popupdisposable.dispose()

Adjuntar ventana emergente de alerta

Usando el método FRange.attachAlertPopup, puede adjuntar una ventana emergente de alerta a la celda inicial de un rango específico.

TypeScript
const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()const fRange = fWorksheet.getRange('A1:B2')const disposable = fRange.attachAlertPopup({  key: 'unique-alert-key', // Unique identifier  title: '这是一个警告!',  message: '这是一个警告!',  width: 300,  height: 200,  // 0: Information  // 1: Warning  // 2: Error  type: 0,})// Remove the alert laterdisposable.dispose()

Agregar DOM flotante a la hoja de trabajo

Usando el método FWorksheet.addFloatDomToPosition, puede agregar un DOM flotante a la hoja de trabajo.

  • Antes de usar este método, debe instalar el @univerjs/sheets-drawing-ui complemento o el ajuste preestablecido @univerjs/preset-sheets-drawing.
  • El DOM flotante es un componente arrastrable que se desplaza sobre la hoja de trabajo y admite almacenamiento persistente.
  • Debe llamar a este método después de que Univer haya terminado de renderizar.
  • componentKey: el identificador único para el componente, utilizado para hacer referencia a él dentro de Univer.
  • Parámetro completo definición
TSX
// You should register the component at an appropriate time (e.g., after Univer has loaded)univerAPI.registerComponent('MyCustomFloatDOMComponent', ({ data }) => (  <div>    Hello    {data?.label}!  </div>))const fWorkbook = univerAPI.getActiveWorkbook()const fWorksheet = fWorkbook.getActiveSheet()// Add a floating DOM to the worksheet// If `disposable` is null, it indicates that the floating DOM was not added successfullyconst disposable = fWorksheet.addFloatDomToPosition({  componentKey: 'MyCustomFloatDOMComponent',  initPosition: {    startX: 100,    endX: 200,    startY: 100,    endY: 200,  },  // The data for the component  data: {    label: 'Univer',  },})// Remove the floating DOMdisposable.dispose()

¿Cómo es esta guía?

© 2026 DreamNum Co., Ltd.