Begin by installing the official Vue adapter package to establish the bridge between the framework and the editor engine.
npm install @wangeditor/editor-for-vue --save
Minimal Component Registration
A basic integration relies on local component binding. The following pattern demonstrates a clean setup using Vue 2's Options API:
<template>
<div class="editor-wrapper">
<RichTextComponent v-model="contentData" />
</div>
</template>
<script>
import RichTextComponent from "@/components/RichTextComponent.vue";
export default {
components: { RichTextComponent },
data() {
return {
contentData: "",
};
},
};
</script>
Encapsulating Editor Logic
Production applications benefit from a dedicated wrapper that isolates lifecycle managemant, configuration, and media processing. This architecture prevents memory leaks and standardizes upload contracts across multiple pages.
<template>
<div class="wang-editor-shell">
<Toolbar
class="panel-toolbar"
:editor="editorRef"
:defaultConfig="toolbarSettings"
mode="default"
/>
<Editor
class="panel-canvas"
v-model="generatedHTML"
:defaultConfig="editingSettings"
mode="default"
@onCreated="attachInstance"
@onChange="propagateChanges"
/>
</div>
</template>
<script>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
export default {
name: "CustomWangEditor",
components: { Editor, Toolbar },
props: {
initialMarkup: { type: String, default: "" }
},
data() {
return {
editorRef: null,
generatedHTML: "",
toolbarSettings: {},
editingSettings: {
placeholder: "Compose your content here...",
MENU_CONF: {
uploadImage: { customUpload: this.dispatchImage },
uploadVideo: { customUpload: this.dispatchVideo }
}
}
};
},
mounted() {
this.$nextTick(() => {
this.generatedHTML = this.initialMarkup;
});
},
methods: {
attachInstance(writableInstance) {
this.editorRef = Object.seal(writableInstance);
},
propagateChanges() {
this.$emit("input", this.generatedHTML);
},
dispatchImage(file, insertionHandler) {
if (!file.type.includes("image")) {
alert("Please select a valid image asset.");
return;
}
const uploadPayload = new FormData();
uploadPayload.append("asset", file);
this.$axios.post("/api/media/upload", uploadPayload, {
headers: { "Content-Type": "multipart/form-data" }
}).then((response) => {
if (response.data.status === 200) {
insertionHandler(
response.data.payload.url,
response.data.payload.alt,
response.data.payload.href
);
} else {
alert(response.data.message || "Asset rejection");
}
}).catch(() => alert("Transmission failed"));
},
dispatchVideo(file, insertionHandler) {
if (!file.type.includes("video")) {
alert("Please select a valid video asset.");
return;
}
const uploadPayload = new FormData();
uploadPayload.append("asset", file);
this.$axios.post("/api/media/upload", uploadPayload, {
headers: { "Content-Type": "multipart/form-data" }
}).then((response) => {
if (response.data.status === 200) {
insertionHandler(response.data.payload.src);
} else {
alert(response.data.message || "Asset rejection");
}
}).catch(() => alert("Transmission failed"));
}
},
beforeDestroy() {
if (this.editorRef) {
this.editorRef.destroy();
}
}
};
</script>
The upload methods assume a backend endpoint returning standardized JSON envelopes. Adjust the query parameters and response extraction to match your server infrastructure.
Mitigating Global Style Collisions
Application-wide CSS resets frequently break inline formatting controls. Overly aggressive normalization removes necessary whitespace, collapses line heights, and disables visual cues like strikethrough or underline states. Isolate resets to the editor scope instead of targeting universal selectors.
/* Avoid blanket resets */
/* * { margin: 0; padding: 0; text-decoration: none; } */
/* Scoped normalization preserves editor internals */
.wang-editor-shell * {
box-sizing: border-box;
outline: none;
}
.wang-editor-shell p,
.wang-editor-shell li,
.wang-editor-shell td {
line-height: 1.6;
margin: 0.8em 0;
}
Theme Injection via Custom Prroperties
The editor accepts dynamic theming through CSS variables. Define these tokens in a shared stylesheet or module-level styles to align the UI with you're design system without patching library files.
:root,
:host {
--we-canvas-bg: #ffffff;
--we-canvas-text: #2c3e50;
--we-border-base: #dcdfe6;
--we-accent-bg: #ecf5ff;
--we-selection-highlight: #b3d8ff;
--we-toolbar-ink: #606266;
--we-disabled-state: #a8abb2;
}
Maintaining these variables ensures consistent rendering across dark/light modes and prevents layout shifts when dynamically switching themes. Import the stylesheet at the framework level to guarantee initialization priority over third-party bundle styles.