Eine Bildergalerie für RichTextEditor in Vue

Der Dialog „Insert Gallery“ von RichTextEditor braucht in einer Vue-App drei Dinge: die Editor-Skripte, die vor der App geladen werden, eine Komponente, die den Editor beim Mounten erstellt und beim Unmounten zerstört, und einen Dev-Server, der die Requests des Dialogs an Ihre API weiterleitet. Diese Seite zeigt ein Setup mit Vite + Vue 3, das alle drei Punkte erfüllt, getestet mit dem Express-Beispiel.
Die Editor-Skripte vor der App laden
Der Editor besteht aus einfachen Browserskripten, die window.RichTextEditor definieren. Sie sind keine ES-Module, deshalb gehören sie in index.html, vor das Modulskript, das Vue mountet:
<!-- Plain browser scripts from public/, loaded before the Vue bundle. -->
<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css">
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<script src="/rte-files.js"></script>Die Dateien liegen in public/richtexteditor/, das Vite unverändert ausliefert. rte-files.js stellt die Upload-Funktionen bereit, die der Editor und die Upload-Schaltfläche der Galerie aufrufen. Klassische Skripte in <head> laufen vor dem Modul-Bundle, daher existiert die globale Variable, sobald die Komponente gemountet wird.
Die Komponente
<script setup>
import { onBeforeUnmount, onMounted, useTemplateRef } from "vue";
// window.RichTextEditor comes from the scripts in index.html.
const props = defineProps({
options: { type: Object, required: true },
initialHtml: { type: String, default: "" },
});
const container = useTemplateRef("container");
let editor = null; // a plain variable: the editor object does not need to be reactive
onMounted(() => {
editor = new window.RichTextEditor(container.value, props.options);
editor.setHTMLCode(props.initialHtml);
});
onBeforeUnmount(() => {
editor?.destroy();
editor = null;
});
defineExpose({ getHTML: () => editor.getHTMLCode() });
</script>
<template>
<div ref="container"></div>
</template>onMountedläuft, sobald dasdivdes Templates im Dokument ist.useTemplateRef("container")(Vue 3.5) gibt dieses Element zurück.onBeforeUnmountruftdestroy()auf, solange das Element noch vorhanden ist. Wir haben das geprüft, indem wir die gesamte App mitapp.unmount()unmountet haben: Im Dokument blieben keine Editor-Elemente zurück, und es gab keine Seitenfehler.- Die Instanz ist eine einfache Variable. Nichts im Template hängt von ihr ab, also muss sie nicht reaktiv sein, und Vue hat keinen Grund, sie in einen Proxy zu verpacken.
defineExposegibt der Elternkomponente eine MethodegetHTML(). Die Schaltfläche „Show HTML“ des Beispiels ruft sie über eine Template-Ref auf und gab<p>Hello from Vue.</p>aus.
Die Elternkomponente übergibt die Optionen einmal. Die Komponente liest sie beim Erstellen des Editors und beobachtet sie nicht:
const options = {
toolbar: "full",
galleryEndpoint: "/rte/gallery", // forwarded to Express by vite.config.js
maxUploadFileSize: 4000000,
};Den API-Server in der Entwicklung erreichen
Der Galerie-Endpoint ist relativ, /rte/gallery, und die Seite wird von Vite auf Port 5112 ausgeliefert. Der Dev-Proxy von Vite leitet die Routen für Galerie und Upload sowie die Bilder an das Express-Beispiel auf Port 5101 weiter:
// /rte/ and /uploads/ go to the Express sample (node-express, port 5101).
// Keep the trailing slashes: "/rte" alone would also catch /rte-files.js.
proxy: {
"/rte/": "http://localhost:5101",
"/uploads/": "http://localhost:5101",
},Der Browser sieht nur einen Origin, also müssen Sie kein CORS konfigurieren. Behalten Sie die abschließenden Schrägstriche bei. Vite vergleicht einen einfachen Schlüssel mit dem Anfang der URL, daher würde "/rte" auch /rte-files.js an Express weiterleiten. Mit demselben Proxy-Block haben wir genau das im React-Beispiel beobachtet. Mit "/rte/" liefert Vite seine eigene Kopie aus.
Verwenden Sie den Proxy nur in der Entwicklung. In der Produktion liefern Sie das gebaute dist/ und die API vom selben Origin aus.
Was der Dialog anzeigt
Das Bild oben zeigt den Editor in dieser Vue-App, nachdem ein Bild aus der Galerie eingefügt wurde. Die Ordner und Bilder kommen vom Express-Server, der in der Galerie-Anleitung für Node.js beschrieben ist. Zwei Einschränkungen stammen von der ausgelieferten Galerie, unabhängig vom Framework. Ihr Formathinweis nennt JFIF, BMP und AVIF, die der Beispielserver ablehnt. Und ein abgelehnter Upload zeigt „Upload failed for <name>.“ statt der Meldung des Servers.
Testen
Laden Sie das Beispielprojekt zu dieser Anleitung und das Express-Beispiel herunter. Starten Sie zuerst Express (npm install, npm start, mit dem Ordner richtexteditor des Editors neben server.mjs). Dann im Vue-Projekt:
npm install
npm run dev
➜ Local: http://localhost:5112/npm run dev kopiert zuerst die Editor-Dateien nach public/. Setzen Sie RTE_DIR auf Ihren Editor-Ordner oder legen Sie den Ordner selbst unter public/richtexteditor ab. Öffnen Sie http://localhost:5112 und klicken Sie auf Insert Gallery. Der Dialog listet die Ordner des Servers auf. New folder und Upload funktionieren über den Proxy, und Insert fügt <img src="/uploads/..."> in den Text ein. Genau diesen Ablauf haben wir in Chromium mit Vue 3.5.44 und Vite 8.3.5 ausgeführt.