Creación de un Editor de Markdown en Tiempo Real con Vue 3 y Marked

La construcción de un editor de Markdown es un proyecto fundamental para comprender la reactividad y la optimización de eventos en aplicaciones modernas. Utilizando Vue 3 y su Composition API, es posible implementar una interfaz fluida que procese texto enriquecido de manera eficiente.

Arquitectura Técnica

Para este desarrollo, se seleccionan herramientas específicas que garantizan un rendimiento óptimo:

  • Vue 3 (script setup): Manejo del estado mediante ref y propiedades calculadas (computed).
  • Marked.js: Un motor de parsing de alto rendimiento para convertir sintaxis Markdown en HTML.
  • Lodash (Debounce): Técnica de control para limitar la frecuencia de ejecución de funciones pesadas durante la entrada de usuario.

Optimización del Procesamiento mediante Debouncing

Uno de los desafíos principales al renderizar Markdown en tiempo real es el costo computacional de transformar el texto en cada pulsación de tecla. Si el usuario escribe rápidamente, la actualización constante de la vista previa puede degradar la experiencia de usuario (UX).

La solución consiste en implementar un retraso controlado. En lugar de actualizar la fuente de datos inmediatamente, empleamos una función debounce que espera a que el usuario deje de escribir durante un periodo determinado (por ejemplo, 200ms) antes de procesar el cambio.


import { debounce } from 'lodash-es';

// Función para actualizar el estado con retraso
const handleInput = debounce((event) => {
  content.value = event.target.value;
}, 200);

Implementación del Componente

El diseño se basa en un sistema de doble panel: una zona de entrada de texto y una zona de visualización. La reactividad de Vue se encarga de sincronizar ambos estados a través de una propiedad computada que invoca al compilador de Markdown.


<script setup>
import { ref, computed } from 'vue';
import { marked } from 'marked';
import { debounce } from 'lodash-es';

// Estado reactivo inicial
const sourceText = ref('# Nuevo documento\nEmpieza a escribir...');

// Transformación de Markdown a HTML mediante computed
const htmlPreview = computed(() => marked.parse(sourceText.value));

// Gestión de eventos con debounce para mejorar el rendimiento
const syncContent = debounce((e) => {
  sourceText.value = e.target.value;
}, 150);
</script>

<template>
  <main class="editor-container">
    <textarea 
      class="source-editor" 
      :value="sourceText" 
      @input="syncContent"
      placeholder="Escribe tu código Markdown aquí..."
    ></textarea>
    
    <section 
      class="preview-pane" 
      v-html="htmlPreview"
    ></section>
  </main>
</template>

<style scoped>
.editor-container {
  display: flex;
  height: 100vh;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.source-editor, .preview-pane {
  flex: 1;
  height: 100%;
  padding: 25px;
  box-sizing: border-box;
  overflow-y: auto;
}

.source-editor {
  border: none;
  border-right: 1px solid #ddd;
  background-color: #fafafa;
  resize: none;
  outline: none;
  font-family: 'Fira Code', monospace;
  font-size: 1rem;
  color: #2c3e50;
}

.preview-pane {
  background-color: #ffffff;
  line-height: 1.6;
}

:deep(pre) {
  background-color: #f1f1f1;
  padding: 10px;
  border-radius: 4px;
}
</style>

Flujo de Datos

  1. El usuario interactúa con el elemento textarea.
  2. El evento @input es capturado por la función syncContent, que está protegida por el debounce.
  3. Una vez trnascurrido el tiempo de espera, la variable reactiva sourceText se actualiza.
  4. La propiedad computada htmlPreview detecta el cambio en su dependencia y ejecuta marked.parse().
  5. Vue actualiza el DOM de forma segura mediante la directiva v-html en el panel de previsualización.

Etiquetas: vue.js marked lodash markdown composition-api

Publicado el 6-9 22:53