PageKit: el creador de sitios GrapesJS autoalojado, con el código fuente incluido. Obtener acceso anticipado

GrapesJS + Vue 3

GrapesJS Vue: Construye un editor visual con Vue 3

Integra el editor visual de código abierto GrapesJS en aplicaciones Vue 3 y Nuxt para crear constructores visuales de páginas, editores CMS, creadores de páginas de destino, editores de correo electrónico y experiencias de edición de marca blanca.

Vue 3Composition APITypeScriptCódigo abiertoHTML y CSSExtensible
Dónde se sienta el editor

Vue alimenta tu aplicación. GrapesJS dirige la edición.

La división merece la pena nombrar antes que cualquier código. Tu aplicación Vue se encarga del enrutamiento, usuarios, permisos y datos. GrapesJS es dueño del lienzo y de todo lo que una persona manipula dentro de él. Ambos se encuentran en un nodo DOM y una llamada de guardado.

  1. Vue 3 application
  2. GrapesJS editor
  3. HTML + CSS + project data
  4. Your API / CMS / SaaS

Nada en esa cadena requiere que Vue sepa cómo funciona el editor, y nada requiere que GrapesJS sepa que está dentro de una app Vue. Por eso la integración es corta.

Respuesta corta

¿Se puede usar GrapesJS con Vue?

Sí. GrapesJS es independiente del framework y puede integrarse directamente en aplicaciones Vue 3. Puedes inicializar el editor con ganchos de ciclo de vida Vue, mantener la instancia del editor en un composable o componente, conectar eventos GrapesJS a tu aplicación Vue y persistir los datos del proyecto a través de tu propio backend.

Dos formas de hacerlo

Integración directa

Importa grapesjs, llama a grapesjs.init() en onMounted(), llama a editor.destroy() en onUnmounted(). No hay dependencia extra, nada entre tú y la API del editor.

Una capa orientada a Vue

Envuelva ese ciclo de vida en tu propio composable — o en un paquete comunitario — para que los componentes tengan una API con forma de Vue en lugar de una imprescindible. Útil cuando más de una pantalla monta un editor.

GrapesJS publica un wrapper oficial de framework, @grapesjs/react, para React. No existe un paquete equivalente de Vue del proyecto GrapesJS, así que cualquier wrapper de Vue que encuentres en npm es un proyecto comunitario. Consulta sus rangos de pares Vue y GrapesJS antes de adoptarlo.

La división del trabajo

¿Qué es GrapesJS para Vue?

Vue 3 es un framework de aplicaciones. GrapesJS es un motor de edición visual. Resuelven diferentes problemas y la integración es limpia precisamente porque no se solapan.

Tu código Vue
  • Enrutamiento
  • Autenticación
  • Permisos
  • Interfaz de aplicación
  • API y capa de datos
En GrapesJS
  • Canvas
  • Drag & drop
  • Component tree
  • Block Manager
  • Style Manager
  • Device Manager
  • UndoManager
  • Commands
  • Serialization
Plugin o adaptador
  • Asset Manager
  • Storage Manager
  • Rich Text Editor
  • Export

Cinco de estos son tuyos. El resto ya existe, y los dos restantes son de configuración y no de construcción.

Paso 1

Instala GrapesJS en Vue 3

Una dependencia. GrapesJS incluye sus propias definiciones de TypeScript, así que no hay un paquete de @types separado para añadir.

npm install grapesjs

Importar la hoja de estilos

El editor no tiene estilo sin ella. En un proyecto Vite o Nuxt puedes importarlo desde el componente o composable que crea el editor; en una app con hoja de estilo global, impórtalo una vez que esté allí.

Lo que necesita la integración

  • Un elemento DOM para el lienzo, accesible a través de una referencia plantilla
  • grapesjs.init(), llamado después de que ese elemento exista
  • editor.destroy() llamado cuando el componente desaparece
  • La hoja de estilo GrapesJS cargó en algún sitio
  • Ejecución solo en navegador — véase la sección Nuxt
Paso 2

Un ejemplo mínimo de Vue 3

Copia esto en un componente y se ejecuta. Todo lo que viene después de esta sección es una adición, no una reescritura.

VisualEditor.vueVUE
<template>
  <div ref="editorContainer" class="editor-shell"></div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, shallowRef, ref } from 'vue';
import grapesjs, { type Editor } from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';

// A template ref: the name matches the ref="" attribute above.
const editorContainer = ref<HTMLDivElement | null>(null);

// shallowRef, not ref — see "Performance" further down the page.
const editor = shallowRef<Editor | null>(null);

onMounted(() => {
  if (!editorContainer.value) return;

  editor.value = grapesjs.init({
    container: editorContainer.value,
    height: '100%',
    fromElement: false,
    storageManager: false,
  });
});

onUnmounted(() => {
  editor.value?.destroy();
  editor.value = null;
});
</script>

<style scoped>
.editor-shell {
  height: 100vh;
}
</style>

Tres cosas que merece la pena destacar

  1. El nombre de referencia de la plantilla coincide con el atributo ref="" — así es como Vue los encaja en <script setup>.

  2. El editor está en shallowRef, no en ref. Vue de lo contrario recorrería todo el grafo de objetos del editor haciéndolo reactivo.

  3. fromElement es falso, así que GrapesJS empieza desde los componentes que pasas en lugar de desde el marcado que había dentro del contenedor.

Ciclo de vida

GrapesJS con el Vue 3 Composition API

Toda la integración es un mapeo del ciclo de vida. Vue te dice cuándo existe el nodo DOM y cuándo está a punto de desaparecer; GrapesJS necesita exactamente esos dos momentos.

VueGrapesJS
onMounted()
grapesjs.init()
El elemento contenedor existe ahora, y solo ahora. Inicializar antes da a GrapesJS un contenedor nulo.
onUnmounted()
editor.destroy()
Elimina oyentes, el iframe de canvas y el DOM del editor. Saltártelo se filtra en cada cambio de ruta.
ref()
elemento contenedor
Una referencia plantilla es el mango contra el que se monta GrapesJS.
shallowRef()
Instancia de editor
Sostiene la instancia sin que sea profundamente reactiva.

Lee de arriba a abajo, ese es todo el contrato entre las dos bibliotecas.

Ni onMounted ni onUnmounted se ejecutan en el servidor, por eso una SPA Vue simple no necesita nada extra. Una aplicación renderizada en servidor necesita un protector más — la sección Nuxt lo cubre.

Reutilizable

Crea un Composable Reutilizable de UseGrapesJS

Cuando una segunda pantalla necesite un editor, mueve el ciclo de vida a un composable. El componente entonces dice lo que quiere, no cómo está cableado el editor.

useGrapesJS.tsTS
// composables/useGrapesJS.ts
import { onMounted, onUnmounted, shallowRef, type Ref } from 'vue';
import grapesjs, { type Editor, type EditorConfig } from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';

type EditorOptions = Omit<EditorConfig, 'container'>;

export function useGrapesJS(
  container: Ref<HTMLElement | null>,
  options: EditorOptions = {},
) {
  const editor = shallowRef<Editor | null>(null);

  const init = (): Editor | undefined => {
    if (editor.value || !container.value) return;

    editor.value = grapesjs.init({
      container: container.value,
      height: '100%',
      fromElement: false,
      storageManager: false,
      ...options,
    });

    return editor.value;
  };

  const destroy = (): void => {
    editor.value?.destroy();
    editor.value = null;
  };

  onMounted(init);
  onUnmounted(destroy);

  return { editor, init, destroy };
}

Usándolo

EditorScreen.vueVUE
<template>
  <div ref="editorContainer" class="editor-shell"></div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { useGrapesJS } from '~/composables/useGrapesJS';

const editorContainer = ref<HTMLElement | null>(null);

const { editor } = useGrapesJS(editorContainer, {
  blockManager: {
    blocks: [
      {
        id: 'hero',
        label: 'Hero',
        category: 'Sections',
        content: '<section>…</section>',
      },
    ],
  },
});
</script>

Lo que te compra el composable

  • Una integración que mantener en lugar de una por pantalla
  • Configuración en un solo lugar
  • Configuración de editor que puede probarse por sí sola
  • Varios editores en una sola app sin copiar y pegar
  • Gestión de eventos compartida entre componentes
  • Componentes que se leen como Vue, no como fontanería DOM

Resiste que esto crezca más de lo necesario. Un composable que envuelve cada módulo GrapesJS en una fachada reactiva es una segunda API para aprender y una segunda cosa para mantener sincronizada.

Reactividad

Conectando eventos GrapesJS con Vue

GrapesJS gestiona el estado del editor. Vue gestiona el estado de la aplicación. Los eventos son la costura: suscríbete a los pocos que tu interfaz realmente refleja y escríbelos en referencias normales.

editor-events.tsTS
import { onMounted, ref, shallowRef } from 'vue';
import type { Editor, Component } from 'grapesjs';

const isReady = ref(false);
const isDirty = ref(false);
const saveState = ref<'idle' | 'saving' | 'saved' | 'error'>('idle');
const selectedName = ref<string | null>(null);

function bindEditorEvents(editor: Editor): void {
  editor.on('load', () => {
    isReady.value = true;
  });

  editor.on('component:selected', (component: Component) => {
    selectedName.value = component?.getName?.() ?? null;
  });

  editor.on('component:update', () => {
    isDirty.value = true;
  });

  editor.on('storage:start:store', () => {
    saveState.value = 'saving';
  });

  editor.on('storage:end:store', () => {
    saveState.value = 'saved';
    isDirty.value = false;
  });

  editor.on('storage:error', () => {
    saveState.value = 'error';
  });
}
EventoQué hace tu interfaz con él
loadOculta el estado de carga una vez que el proyecto esté en el lienzo
component:selectedMuestra qué elemento está seleccionado en tu propia barra de herramientas
component:updateMarca el documento como sucio, activa el botón de guardar
storage:start:storeMostrar un indicador de ahorro
storage:end:storeShow salvado, despejad la bandera sucia
storage:errorSuperar un fallo sobre el que el usuario puede actuar

Imita lo que muestras, no lo que tenga el editor. Copiar el árbol de componentes en una tienda Vue te da dos fuentes de verdad y un error de sincronización.

Nuxt & SSR

Usando GrapesJS con Nuxt

GrapesJS depende de las APIs DOM del navegador, así que la inicialización del editor solo debería ocurrir en un contexto de navegador. En Nuxt eso significa mantener el editor fuera del renderizado del servidor — todo lo demás es la misma integración que ya tienes.

pages/editor.vueVUE
<!-- pages/editor.vue -->
<template>
  <ClientOnly>
    <VisualEditor />

    <template #fallback>
      <p class="editor-placeholder">Loading the editor…</p>
    </template>
  </ClientOnly>
</template>
components/VisualEditor.client.vueVUE
<!-- components/VisualEditor.client.vue -->
<template>
  <div ref="editorContainer" class="editor-shell"></div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { useGrapesJS } from '~/composables/useGrapesJS';

// Reached only in the browser: the .client suffix keeps this
// component out of the server render, and onMounted never runs
// on the server anyway.
const editorContainer = ref<HTMLElement | null>(null);
const { editor } = useGrapesJS(editorContainer);
</script>

Dos opciones correctas

<ClientOnly>

Envuelve el editor donde se usa. La ranura de respaldo le da al servidor algo para renderizar, así que no hay fotograma en blanco antes de la hidratación.

Un componente .client

La propia convención de nombres de Nuxt: un componente cuyo nombre de archivo termina en .client solo se renderiza en el navegador. Útil cuando el editor se usa en varios lugares.

Ambos son válidos y se combinan. Ninguno es necesario para GrapesJS — lo que GrapesJS requiere es simplemente que init() se ejecute donde existe el documento.

Arquitectura

Donde cae el límite

SSR renderiza el shell de la aplicación. GrapesJS se ejecuta en el navegador. Nombrar ese límite es lo que hace que una integración con Nuxt sea predecible en lugar de ser una fuente de errores de hidratación.

  1. Aplicación Nuxt
  2. SSR / shell de aplicación
  3. Editor visual solo para clientes
  4. GrapesJS
  5. API / CMS / base de datos

La pantalla del editor no es una página que renderizas en servidor para SEO, es una herramienta autenticada. Las páginas que produce son las que renderizas e indexas, y esas son HTML y CSS simples.

Crea un creador de páginas Vue completo
Decisión

¿Necesitas un envoltorio Vue para GrapesJS?

No. La integración directa es una forma completa y soportada de usar GrapesJS, y es lo que hacen los ejemplos de esta página. Un envoltorio es una comodidad, no un requisito.

EnfoqueMejor paraCompensación
GrapesJS directoControl máximoTú mismo escribes el ciclo de vida — unas quince líneas.
Envoltorio / integración VueUna API más orientada a VueUna dependencia entre tú y la API del editor, en el calendario de lanzamientos de otra persona.
Composición personalizadaIntegración de aplicaciones reutilizablesEs tuyo para mantener — pero es el archivo que se muestra arriba, y no se vuelve obsoleto.

Lo que realmente se publica

Vale la pena comprobarlo antes de adoptar nada, porque los resultados de búsqueda de esta pregunta son más antiguos que los paquetes que describen.

Envoltorio oficial de React
@grapesjs/react 2.0.0, MIT, publicados por los mantenedores de GrapesJS.
Envoltorio oficial de Vue
Ninguno. El proyecto GrapesJS no publica un paquete Vue.
Paquete comunitario Vue
vue-grapesjs 0.1.0 es un proyecto de terceros, publicado por última vez 2022-05-23, con rangos homólogos vue@^2.6.6 y grapesjs@^0.14.55 — Vue 2 y un GrapesJS mucho más antiguo.

Comprobado con el registro npm en 2026-09-02. Si encuentras un paquete Vue más reciente, lee primero su peerDependencies: ese campo te indica si apunta a Vue 3 y a un GrapesJS actual.

Para Vue 3 hoy, el componible anterior es el envoltorio. Son unas veinte líneas, usa directamente la API de GrapesJS y no puede quedarse atrás de una versión de la que dependes.

Más allá de la integración

Crea un Constructor de Páginas Vue con GrapesJS

Montar el editor es la primera tarde. Un creador de páginas en el que tus usuarios confíen es el resto del trabajo, y en su mayoría es la configuración de los módulos que GrapesJS ya extiene.

  • Canvas

    La superficie editable y los anchos de sus dispositivos.

  • Components

    Los tipos que tus usuarios pueden situar y sus rasgos.

  • Blocks

    La paleta de la que se arrastran.

  • Style Manager

    Qué propiedades CSS están expuestas y a quién.

  • Asset Manager

    Imágenes y medios, desde tu almacenamiento.

  • Storage Manager

    Donde se cargan y guardan los datos del proyecto.

  • Commands

    Acciones nombradas, vinculables a tu propia interfaz.

  • Device Manager

    Puntos de interrupción responsivos para la edición y la producción.

  • Plugins

    Todo lo anterior, empaquetado y reutilizable.

Aprende a construir un creador de páginas completo Vue
Lo que puedes construir

¿Qué puedes construir con GrapesJS y Vue?

El mismo núcleo del editor, configurado de forma diferente. Cada uno de estos es un conjunto distinto de bloques, un destino de almacenamiento distinto y un paso de publicación distinto.

Producción

¿Qué almacena y genera GrapesJS?

Tres cosas que son fáciles de confundir y caras de confundir. Acertar desde el primer día es lo que hace que un documento pueda ser reeditado un año después.

Datos del proyecto

El estado editable del proyecto GrapesJS — páginas, componentes, estilos, recursos. Léelo con editor.getProjectData(), restaura con editor.loadProjectData(). Esto es lo que debe persistir.

HTML

El marcado renderizado, de editor.getHtml(). Regéneralo cada vez que publiques. Es la salida, no la fuente.

CSS

Los estilos que produjo el editor, de editor.getCss(). La misma regla: generado, no almacenado como fuente de verdad.

  1. User edits
  2. GrapesJS project data
  3. Your API / database
  4. HTML + CSS
  5. Preview / publish

Almacena datos editables del proyecto. Genera HTML y CSS cuando necesites renderizar o publicar.

Guardar solo el HTML renderizado es el error que no se puede deshacer después. Siempre puedes regenerar HTML a partir de datos del proyecto; no puedes recuperar datos del proyecto de forma fiable desde HTML.

publish.tsTS
// Editable state — store this, it is what the editor reloads.
const projectData = editor.getProjectData();

// Rendered output — regenerate this whenever you publish.
const html = editor.getHtml();
const css = editor.getCss();

await fetch(`/api/projects/${projectId}/publish`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ projectData, html, css }),
});

// Sanitize `html` on the server before it is served to anyone.
Persistencia

Guarda proyectos GrapesJS en tu aplicación Vue

A GrapesJS no le importa cuál sea tu backend. Un adaptador de almacenamiento son dos funciones asíncronas — una que devuelve los datos del proyecto y otra que los acepta — así que el editor se comunica con la API que ya tienes.

  1. Vue
  2. GrapesJS storage
  3. REST API
  4. Backend
  5. Database
storage.tsTS
import grapesjs, { type ProjectData } from 'grapesjs';

// Wherever your app keeps it — a route param, a prop, a store.
const projectId = props.projectId;

const editor = grapesjs.init({
  container: editorContainer.value!,
  fromElement: false,
  storageManager: {
    type: 'app-api',
    autosave: true,
    stepsBeforeSave: 10,
  },
  // Registered as a plugin so the adapter exists before
  // GrapesJS performs its first load.
  plugins: [
    (ed) => {
      ed.Storage.add('app-api', {
        async load(): Promise<ProjectData> {
          const res = await fetch(`/api/projects/${projectId}`);
          if (!res.ok) {
            throw new Error(`Load failed: ${res.status}`);
          }
          return await res.json();
        },

        async store(data: ProjectData) {
          const res = await fetch(`/api/projects/${projectId}`, {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ projectData: data }),
          });
          if (!res.ok) {
            throw new Error(`Save failed: ${res.status}`);
          }
        },
      });
    },
  ],
});

Lo que cubre el adaptador

load()
Recupera el proyecto cuando abra el editor.
store()
Envía los datos del proyecto a tu endpoint.
autosave
Se dispara tras un número determinado de cambios, mediante stepsBeforeSave.
Project JSON
El estado serializado — la versión que tú mismos.
Versioning
Mantén las cargas útiles anteriores en el lado del servidor para soportar el rollback.
Publishing
Un endpoint separado que renderiza y limpia la salida.

Registrar el adaptador a través del array de plugins importa: garantiza que el almacenamiento exista antes de que GrapesJS realice su primera carga.

Medios de comunicación

Gestiona los activos en tu aplicación Vue

El gestor de activos es una interfaz de usuario sobre un endpoint. Apúntalo a la tuya y todas las reglas existentes — autenticación, validación, cuotas, CDN — siguen aplicándose.

assets.tsTS
// Fetched from your own API before the editor is created.
const assets = await fetch('/api/assets').then((res) => res.json());

const editor = grapesjs.init({
  container: editorContainer.value!,
  assetManager: {
    assets,

    // Uploads go to your endpoint, with your auth and
    // your validation.
    upload: '/api/assets',
    uploadName: 'files',
    multiUpload: true,
    autoAdd: true,
    headers: { Authorization: `Bearer ${token.value}` },
    credentials: 'same-origin',

    // Reject what the backend would reject anyway,
    // before the round trip.
    beforeUpload: (files: File[]) => {
      const limit = 5 * 1024 * 1024;
      const tooBig = files.some((f) => f.size > limit);
      if (tooBig) {
        toast.error('Images must be under 5 MB');
        return false;
      }
    },
  },
});
upload
Tu endpoint; uploadName es el campo de formulario en el que se publica.
assets
Súlva el gestor con URLs que tu API ya conoce.
headers / credentials
Se envía con cada subida, así que tu autorización actual sigue aplicando.
beforeUpload
Rechaza el lado del cliente; tu servidor sigue validando.
Storage & CDN
GrapesJS nunca ve dónde caen los bytes: almacena la URL que devuelves.
Asset URLs
Lo que acaba en el HTML publicado, así que sírvelos desde un origen duradero.
Tu vocabulario

Crear componentes GrapesJS personalizados para aplicaciones Vue

Un tipo de componente personalizado es la forma en que el editor aprende tu producto. Tiene su propio panel de ajustes, sus propias reglas de caída y su propio bloque en la paleta.

pricing-card.tsTS
import type { Editor } from 'grapesjs';

export function pricingCardPlugin(editor: Editor): void {
  editor.Components.addType('pricing-card', {
    isComponent: (el) => el.dataset?.gjsType === 'pricing-card',
    model: {
      defaults: {
        tagName: 'section',
        attributes: { 'data-gjs-type': 'pricing-card' },
        // Traits become the settings panel for this component.
        traits: [
          { type: 'text', name: 'plan', label: 'Plan name' },
          { type: 'text', name: 'price', label: 'Price' },
          { type: 'checkbox', name: 'featured', label: 'Featured' },
        ],
        components: `
          <h3 data-gjs-type="text">Starter</h3>
          <p data-gjs-type="text">$0 / month</p>
          <a href="#">Choose plan</a>
        `,
      },
    },
  });

  editor.Blocks.add('pricing-card', {
    label: 'Pricing card',
    category: 'Marketing',
    content: { type: 'pricing-card' },
  });
}

// Pass it to the editor like any other plugin:
// grapesjs.init({ container, plugins: [pricingCardPlugin] })

Típicos primeros cinco

  • Hero
  • Pricing card
  • Product card
  • Form
  • Navigation

Los componentes personalizados también son la forma de restringir el editor. Configurar desplegable o arrastrable en un tipo es lo que impide que un usuario deje caer una tarjeta de precios dentro de una barra de navegación, y los rasgos son los que le dan un campo etiquetado en lugar de un control CSS en bruto.

Estos son tipos de componentes GrapesJS, no componentes Vue. El lienzo renderiza DOM; tus componentes Vue renderizan tu aplicación alrededor de él.

Ecosistema

Extiende tu editor Vue con plugins GrapesJS

Un plugin es una función que recibe el editor — la misma firma de función, ya sea que venga de npm, de GJS.Market o de tu propio repositorio. A ninguno le importa que la aplicación anfitriona sea Vue.

plugins.tsTS
import grapesjs from 'grapesjs';
import basicBlocks from 'grapesjs-blocks-basic';
import { pricingCardPlugin } from '~/editor/pricing-card';

const editor = grapesjs.init({
  container: editorContainer.value!,
  plugins: [
    // Options go through a wrapper function: `pluginsOpts`
    // is keyed by string, so it only reaches plugins that
    // were passed to `plugins` by name.
    (ed) => basicBlocks(ed, { flexGrid: true }),
    pricingCardPlugin,
  ],
});

Construir vs adoptar

¿Construir tú mismo el editor visual o usar GrapesJS?

No es un argumento de que construir está mal, sino un inventario de lo que significa construir. Cada fila es un subsistema que existe, lo hayas planeado o no.

CapacidadConstrúeteGrapesJS
CanvasConstrucciónIncluido
Drag & dropConstrucciónIncluido
ComponentsConstrucciónIncluido
BlocksConstrucciónIncluido
Style ManagerConstrucciónIncluido
Asset ManagerConstrucciónExtensible
Storage ManagerConstrucciónExtensible
PluginsConstruir un ecosistemaArquitectura de plugins
Vue integrationNativoAgnóstico respecto al marco

Vue te da el marco de la aplicación. GrapesJS te da el motor de edición visual.

¿Por qué no construir el editor completamente con componentes Vue?

Porque los componentes de Vue son bloques constructores de aplicaciones, y un editor visual necesita algo más encima: gestión de canvas, un árbol de componentes con reglas de drop, selección y estado de hover, una capa de estilo que escriba CSS real, cambio de dispositivo, deshacer y rehacer todo eso, gestión de activos, serialización, comandos con nombre y un punto de extensión para todo. Puedes construir eso en Vue — simplemente es un proyecto diferente al que te propusiste.

Vue + GrapesJS es una propuesta diferente a los componentes Vue por sí solos.

En producción

Arquitectura de producción para GrapesJS + Vue

Cómo se sitúa el editor dentro de una aplicación real, una vez que hay usuarios, permisos y más de un proyecto.
  1. Vue / Nuxt

    Tu aplicación Nuxt o Vue: el shell, la sesión y quién puede abrir qué proyecto.

    • Application UI
    • Authentication
    • Users
    • Permissions
  2. GrapesJS

    El editor, montado en una pantalla. Recibe un proyecto y emite un proyecto.

    • Canvas
    • Components
    • Blocks
    • Styles
    • Assets
  3. Application API

    Tus propias rutas. GrapesJS los llama a través de los adaptadores de almacenamiento y activos que has escrito.

  4. Backend

    Donde realmente viven proyectos, medios, usuarios y versiones — sin cambios por el editor que está encima.

    • Projects
    • Assets
    • Users
    • Versions

El editor es una hoja en ese árbol, no la raíz. Todo lo que está encima es código que habrías escrito de todas formas.

Rendimiento

Consideraciones de rendimiento

  • No hagas que el editor reaccione profundamente

    Este es el que realmente muerde. shallowRef, o una variable con alcance de módulo — nunca ref() alrededor de la instancia del editor. Vue recorrería un grafo de objetos muy grande y reejecutaría efectos sobre el churn interno.

  • Inicializar solo cuando sea necesario

    Crea el editor en la pantalla que edita, no en un layout o un almacén que monten todas las rutas.

  • Carga perezosamente el editor

    GrapesJS es un paquete considerable. Cárgalo en su propio bloque asíncrono para que las rutas que nunca editen nunca paguen por ello.

  • Mantén las actualizaciones fuera del estado global

    Enviar cada component:update a una tienda convierte cada pulsación de tecla en un renderizado a nivel de aplicación.

  • Paginar colecciones de grandes activos

    Semilla el gestor de activos desde un endpoint paginado en lugar de enviar miles de URLs al editor.

  • Mantén los árboles de componentes manejables

    Los documentos muy profundos cuestan más de renderizar, serializar y diferenciar. La estructura se fomenta a sí misma si tus bloques lo hacen.

Seguridad

Consideraciones de seguridad

Un editor visual es un sistema que acepta HTML creado por el usuario. Trátalo así.

Sanitize HTML publicado
Desinfecta el servidor, en el momento de publicar, antes de que se sirva nada a un visitante.
Validar subidas
Tipo, tamaño y contenido — las comprobaciones del lado del cliente son UX, no aplicación.
Autenticar los extremos de almacenamiento
Cargar y guardar son rutas API ordinarias y necesitan autenticación ordinaria.
Hacer cumplir permisos en el lado del servidor
Ocultar un panel en el editor no es un modelo de autorización.
Validar los datos del proyecto
Llega de un cliente y puede ser cualquier cosa. Compróvalo antes de guardarlo.
Nunca confíes en el estado del editor
Cualquier cosa que el navegador envíe sobre lo editado es una afirmación, no un hecho.
Proteger los endpoints de publicación
La publicación cambia lo que ve el público; limita la tarifa y la autoriza en consecuencia.
Resolución de problemas

Errores comunes de GrapesJS + Vue

Casi todos los problemas de integración reportados para esta combinación son uno de estos siete.

Inicialización antes de la montada

Síntoma

El contenedor es nulo, o el editor se renderiza en nada.

Arreglar

Crea el editor dentro de onMounted(). La referencia de la plantilla no tiene ningún elemento antes de eso.

Olvidando la limpieza

Síntoma

La memoria crece y los oyentes aburridos disparan tras abandonar la ruta.

Arreglar

Llama a editor.destroy() en onUnmounted() y borra la referencia.

Haciendo que todo el editor reaccione profundamente

Síntoma

El editor se siente lento; las herramientas de desarrollo de Vue se estancan.

Arreglar

Mantén la instancia en shallowRef, o fuera completamente de la reactividad Vue.

Inicialización de GrapesJS durante SSR

Síntoma

El documento no está definido, o hay una descoordinación de hidratación en la ruta del editor.

Arreglar

Renderiza el editor solo para el cliente — <ClientOnly>, un componente .client, o ambos.

Mezcla del estado del editor con el estado de la aplicación

Síntoma

Dos fuentes de verdad, y ediciones que desaparecen en la navegación.

Arreglar

Deja que GrapesJS sea el dueño del proyecto; refleja solo los pocos valores que muestra tu interfaz.

Olvidando la importación CSS

Síntoma

El editor carga, pero los paneles no tienen estilo ni se pueden usar.

Arreglar

Importa grapesjs/dist/css/grapes.min.css, o inclúyelo en tu hoja de estilos global.

Copiar ejemplos de envoltorios desactualizados

Síntoma

Errores de tipo, o una integración basada en ganchos de ciclo de vida Vue 2.

Arreglar

Revisa peerDependencies antes de adoptar cualquier envoltorio. Varios ejemplos populares son anteriores a Vue 3.

En Vue 2 la misma integración usa mounted() y beforeDestroy() en lugar de onMounted() y onUnmounted(); el lado GrapesJS no ha cambiado. El nuevo trabajo debería dirigirse a Vue 3 — todo en esta página lo asume.

Antes de que envíes

Lista de verificación de producción Vue + GrapesJS

El orden coincide más o menos con el orden en que esta página los presentó.

  1. Instalar GrapesJS
  2. Inicializar después de la montura
  3. Destruir al desmontar
  4. Importar el CSS del GrapesJS
  5. Gestionar la ejecución SSR / solo cliente
  6. Decidir integración directa vs envoltorio
  7. Crea un composable reutilizable cuando sea útil
  8. Conecta los eventos del editor que refleja tu interfaz
  9. Configurar almacenamiento
  10. Configurar activos
  11. Añadir componentes personalizados
  12. Añade los plugins que tu producto necesite
  13. Implementar permisos en el lado del servidor
  14. Sanitizar el contenido publicado
  15. Edición responsiva a pruebas
  16. Prueba la versión de producción
Preguntas frecuentes

GrapesJS y Vue: Preguntas frecuentes

¿Puedo usar GrapesJS con Vue 3?

Sí. GrapesJS es una biblioteca independiente del framework que se renderiza en un elemento DOM, así que funciona en Vue 3 sin adaptador. Inicialízalo en onMounted() y destrúyelo en onUnmounted().

¿Cómo instalo GrapesJS en Vue?

Ejecuta npm e instala grapesjs. El paquete incluye sus propias definiciones TypeScript. También necesitas cargar su hoja de estilo, ya sea importando grapesjs/dist/css/grapes.min.css o incluyéndolo en tu CSS global.

¿Cómo inicializo GrapesJS en Vue 3?

Crea una referencia plantilla en el elemento contenedor y luego llama a grapesjs.init({ container: containerRef.value }) dentro de onMounted(). El elemento no existe antes de montar, así que inicializar cualquier elemento anterior no da a GrapesJS nada en qué renderizar.

¿Puedo usar GrapesJS con el Composition API?

Sí, y es la forma recomendada. onMounted() y onUnmounted() se asignan directamente a grapesjs.init() y editor.destroy(), y toda la integración cabe en un único composable.

¿Puedo usar GrapesJS con <script setup>?

Sí. Todos los ejemplos en esta página usan <script setup lang="ts">. Una referencia plantilla declarada con ref() se vincula automáticamente al atributo ref="" correspondiente.

¿GrapesJS funciona con Nuxt?

Sí. La integración es idéntica a la del Vue 3 simple; la única novedad es mantener el editor fuera del renderizado del servidor, con <ClientOnly> o un componente .client.

¿Funciona GrapesJS con Nuxt SSR?

Sí, con el editor renderizado solo por cliente. GrapesJS necesita APIs DOM de navegador, así que no puede ejecutarse durante un renderizado en servidor — pero las páginas que produce son HTML y CSS simples, y esas son exactamente las que renderizas e indexas en servidor.

¿Necesito un wrapper Vue para GrapesJS?

No. La integración directa es un enfoque completo y es lo que usan los ejemplos aquí. GrapesJS publica un envoltorio oficial de React pero no un equivalente a Vue, así que cualquier envoltorio de Vue en npm es un proyecto comunitario — revisa sus rangos de pares Vue y GrapesJS antes de adoptarlo.

¿Puedo usar GrapesJS con TypeScript?

Sí. GrapesJS incluye las definiciones de TypeScript en el paquete, así que el tipo Editor y el objeto de configuración se tipifican sin una dependencia @types adicional.

¿Puedo guardar proyectos GrapesJS en mi backend Vue?

Sí. Registra un adaptador de almacenamiento con editor.Storage.add() que implemente load() y store(). Ambos son funciones asíncronas ordinarias, así que pueden llamar a la API que ya tengas.

¿Puedo crear componentes personalizados con GrapesJS?

Sí. editor.Components.addType() define un tipo de componente con sus propios rasgos y reglas de drop, y editor.Blocks.add() lo coloca en la paleta. Así es como el editor aprende el vocabulario de tu producto.

¿Puedo usar plugins GrapesJS con Vue?

Sí. Un plugin GrapesJS es una función que recibe la instancia del editor, así que no se ve afectada por el framework que la aloja. Pasa plugins en el array de plugins de grapesjs.init().

¿Puedo crear un creador de páginas Vue con GrapesJS?

Sí — ese es el caso común. Montar el editor es la parte corta; el resto consiste en configurar bloques, almacenamiento, recursos y permisos alrededor de él.

Construye tu editor visual Vue con GrapesJS

Integra el motor de edición visual en tu aplicación Vue o Nuxt, mantén el control de tus datos y salidas, y amplía el editor con los plugins que tu producto necesite.

Construye tu aplicación con Vue 3. Añade edición visual con GrapesJS.

Sigue leyendo

Guías relacionadas