Importar Web SDK a través de CDN
Ejecuta primero el ejemplo completo y después cópialo en tu página. Incluye las dependencias, estilos, idiomas y registros Facade necesarios para una hoja editable con cálculo de fórmulas.
Prueba una hoja editable
- Abre el ejemplo o guarda el HTML siguiente como
index.html. - Ábrelo en un navegador moderno con conexión a Internet. No necesita compilador ni servidor. La interfaz y los datos del ejemplo están en español.
- El total del cuaderno es 36. Cambia la cantidad de 3 a 4: el total pasa a 48. También puedes editar celdas y deshacer cambios.
Ejemplo HTML completo
Este ejemplo usa React 18.3.1 UMD. Su objeto global React no expone jsx y jsxs, que necesitan los bundles UMD de Univer. Las dos líneas siguientes proporcionan esas entradas mediante la API pública React.createElement. Con un gestor de paquetes, la herramienta de compilación resuelve react/jsx-runtime; no copies este puente UMD en esa configuración.
Los recursos se cargan desde jsDelivr en orden de dependencia. Si una solicitud falla, el ejemplo vuelve a intentar la misma versión en unpkg antes de continuar. Si ambos proveedores fallan, se detiene el inicio y se muestra el recurso que no se pudo cargar.
<!doctype html><html lang="es-ES"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Ejemplo CDN de Univer Sheets</title> <style> html, body, #root, #app { padding: 0; margin: 0; height: 100%; } </style> </head> <body> <div id="app"><p role="status" style="padding: 24px; font-family: system-ui">Cargando Univer…</p></div> <script> const cdnBases = ['https://cdn.jsdelivr.net/npm/', 'https://unpkg.com/'] const app = document.getElementById('app') async function loadResource(path, tag = 'script') { for (const base of cdnBases) { const element = document.createElement(tag) const url = base + path element.crossOrigin = 'anonymous' if (tag === 'link') { element.rel = 'stylesheet' element.href = url } else { element.src = url } try { await new Promise((resolve, reject) => { element.onload = () => resolve() element.onerror = () => reject(new Error(url)) document.head.appendChild(element) }) return } catch { element.remove() } } throw new Error(`Could not load ${path} from ${cdnBases.join(' or ')}`) } const styles = [ '@univerjs/design@1.4.0/lib/index.css', '@univerjs/ui@1.4.0/lib/index.css', '@univerjs/docs-ui@1.4.0/lib/index.css', '@univerjs/sheets-ui@1.4.0/lib/index.css', '@univerjs/sheets-formula-ui@1.4.0/lib/index.css', '@univerjs/sheets-numfmt-ui@1.4.0/lib/index.css', ] const reactScripts = [ 'react@18.3.1/umd/react.production.min.js', 'react-dom@18.3.1/umd/react-dom.production.min.js', ] const sdkScripts = [ 'rxjs@7.8.2/dist/bundles/rxjs.umd.min.js', '@wendellhu/redi@1.1.3/dist/umd/index.js', '@wendellhu/redi@1.1.3/dist/umd/react-bindings/index.js', '@univerjs/themes@1.4.0/lib/umd/index.js', '@univerjs/protocol@1.4.0/lib/umd/index.js', '@univerjs/core@1.4.0/lib/umd/index.js', '@univerjs/network@1.4.0/lib/umd/index.js', '@univerjs/rpc@1.4.0/lib/umd/index.js', '@univerjs/design@1.4.0/lib/umd/index.js', '@univerjs/engine-render@1.4.0/lib/umd/index.js', '@univerjs/engine-formula@1.4.0/lib/umd/index.js', '@univerjs/drawing@1.4.0/lib/umd/index.js', '@univerjs/telemetry@1.4.0/lib/umd/index.js', '@univerjs/ui@1.4.0/lib/umd/index.js', '@univerjs/docs@1.4.0/lib/umd/index.js', '@univerjs/docs-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets@1.4.0/lib/umd/index.js', '@univerjs/sheets-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets-formula@1.4.0/lib/umd/index.js', '@univerjs/sheets-formula-ui@1.4.0/lib/umd/index.js', '@univerjs/sheets-numfmt@1.4.0/lib/umd/index.js', '@univerjs/sheets-numfmt-ui@1.4.0/lib/umd/index.js', '@univerjs/core@1.4.0/lib/umd/facade.js', '@univerjs/engine-formula@1.4.0/lib/umd/facade.js', '@univerjs/ui@1.4.0/lib/umd/facade.js', '@univerjs/docs@1.4.0/lib/umd/facade.js', '@univerjs/docs-ui@1.4.0/lib/umd/facade.js', '@univerjs/sheets@1.4.0/lib/umd/facade.js', '@univerjs/sheets-ui@1.4.0/lib/umd/facade.js', '@univerjs/sheets-formula@1.4.0/lib/umd/facade.js', '@univerjs/sheets-numfmt@1.4.0/lib/umd/facade.js', '@univerjs/design@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/ui@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/sheets@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/sheets-ui@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/docs-ui@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/sheets-formula-ui@1.4.0/lib/umd/locale/es-ES.js', '@univerjs/sheets-numfmt-ui@1.4.0/lib/umd/locale/es-ES.js', ] // Fetch ahead in parallel; main() still executes scripts in dependency order. for (const [as, paths] of [ ['style', styles], ['script', [...reactScripts, ...sdkScripts]], ]) { for (const path of paths) { const preload = document.createElement('link') preload.rel = 'preload' preload.as = as preload.crossOrigin = 'anonymous' preload.href = cdnBases[0] + path preload.onerror = () => { preload.onerror = null preload.href = cdnBases[1] + path } document.head.appendChild(preload) } } async function main() { for (const path of styles) await loadResource(path, 'link') for (const path of reactScripts) await loadResource(path) // Bridge the React 18 UMD global to the JSX runtime expected by Univer UMD bundles. React.jsx = (type, props, key) => React.createElement(type, key === undefined ? props : { ...props, key }) React.jsxs = React.jsx for (const path of sdkScripts) await loadResource(path) app.textContent = '' const { Univer, LocaleType, mergeLocales, UniverInstanceType } = UniverCore const { FUniver } = UniverCoreFacade const { UniverRenderEnginePlugin } = UniverEngineRender const { UniverFormulaEnginePlugin } = UniverEngineFormula const { UniverUIPlugin } = UniverUi const { UniverSheetsPlugin } = UniverSheets const { UniverSheetsUIPlugin } = UniverSheetsUi const { UniverDocsPlugin } = UniverDocs const { UniverDocsUIPlugin } = UniverDocsUi const { UniverSheetsFormulaPlugin } = UniverSheetsFormula const { UniverSheetsFormulaUIPlugin } = UniverSheetsFormulaUi const { UniverSheetsNumfmtPlugin } = UniverSheetsNumfmt const { UniverSheetsNumfmtUIPlugin } = UniverSheetsNumfmtUi const univer = new Univer({ locale: LocaleType.ES_ES, locales: { [LocaleType.ES_ES]: mergeLocales( UniverDesignEsES, UniverUiEsES, UniverSheetsEsES, UniverSheetsUiEsES, UniverDocsUiEsES, UniverSheetsFormulaUiEsES, UniverSheetsNumfmtUiEsES, ), }, }) univer.registerPlugin(UniverRenderEnginePlugin) univer.registerPlugin(UniverFormulaEnginePlugin) univer.registerPlugin(UniverUIPlugin, { container: 'app', }) univer.registerPlugin(UniverDocsPlugin) univer.registerPlugin(UniverDocsUIPlugin) univer.registerPlugin(UniverSheetsPlugin) univer.registerPlugin(UniverSheetsUIPlugin) univer.registerPlugin(UniverSheetsFormulaPlugin) univer.registerPlugin(UniverSheetsFormulaUIPlugin) univer.registerPlugin(UniverSheetsNumfmtPlugin) univer.registerPlugin(UniverSheetsNumfmtUIPlugin) univer.createUnit(UniverInstanceType.UNIVER_SHEET, {}) const univerAPI = FUniver.newAPI(univer) window.univerAPI = univerAPI univerAPI .getActiveWorkbook() .getActiveSheet() .getRange('A1:D3') .setValues([ ['Artículo', 'Cantidad', 'Precio', 'Total'], ['Cuaderno', 3, 12, '=B2*C2'], ['Bolígrafo', 5, 2, '=B3*C3'], ]) } main().catch((error) => { console.error(error) app.setAttribute('role', 'alert') app.style.cssText = 'padding: 24px; box-sizing: border-box; white-space: pre-wrap; overflow-wrap: anywhere; font: 14px/1.5 system-ui' app.textContent = 'No se pudo cargar el ejemplo. Comprueba la conexión y actualiza la página.' + '\n' + error.message }) </script> </body></html>Convenciones de nombres
Los scripts UMD exponen las exportaciones de los módulos como objetos globales. Usa estos nombres para acceder a plugins y API Facade en el código de inicialización:
| Paquete o punto de entrada | Nombre global |
|---|---|
@univerjs/core | UniverCore |
@univerjs/docs-ui | UniverDocsUi |
@univerjs/core/facade | UniverCoreFacade |
@univerjs/docs-ui/locale/es-ES | UniverDocsUiEsES |
Mantener versiones coherentes
El ejemplo fija Univer en 1.4.0, React y ReactDOM en 18.3.1, y RxJS en 7.8.2. Al actualizar, cambia juntas todas las URL de Univer, incluidas Facade, CSS e idiomas. Evita cargar otra copia de bibliotecas que ya estén en el bundle de tu aplicación.
Solución de problemas
| Síntoma | Qué comprobar |
|---|---|
ITelemetryService | Carga @univerjs/telemetry antes de @univerjs/sheets-ui, que depende de él. Conserva la lista completa de dependencias. |
FDocument | Carga @univerjs/docs/facade antes de @univerjs/docs-ui/facade; Sheets también usa el motor de texto de Docs. |
[redi], t is not a function | Parte del ejemplo completo, con una sola copia de cada dependencia y versiones coherentes. Comprueba las solicitudes fallidas en Network. |
| Editor en blanco | Asigna una altura al contenedor. Si la red o CSP bloquea el CDN, aloja las dependencias o usa un gestor de paquetes. |
Para una aplicación React o Vue existente, utiliza la instalación mediante gestor de paquetes, que gestiona las dependencias sin mantener una larga lista de scripts.
¿Cómo es esta guía?