Vue and React DOCX editor API comparison
Compare the Vue and React DOCX editor APIs: props, composables, hooks, refs, events, slots, and component composition.
@docx-editor.dev/vue and @docx-editor.dev/react are two adapters over one engine. They share the OOXML parser, the command set, and the composition primitives.
This post covers the API differences between the adapters. For installation, loading, and saving, use the Vue DOCX editor guide or the React Word editor guide.
Compare the props
Both adapters take the same document and chrome props: document, mode, title, author, locale, i18n, t, fonts, zoom, zoomMode, menu, navigation, rulers, chrome, hyperlinkPopup, contextMenu, and modules. The document prop accepts an ArrayBuffer, a Uint8Array, a DocumentHandle, or the string 'blank'.
The adapters have four prop differences:
- React takes callback props:
onReady,onChange,onFontError,onSave,onOpen, andonTitleChange. Vue takes the first three as events on<DocxEditorRoot>, described in Events instead of callback props. - Vue adds
colorMode, which accepts'light','dark', or'system'. - Styling uses
classNamein React andclassin Vue. - React accepts
childrenas a prop. Vue uses slots.
Vue binds props with v-bind, so a prop with a value needs a colon:
<script setup lang="ts">
import { DocxEditor } from '@docx-editor.dev/vue';
import '@docx-editor.dev/vue/styles.css';
defineProps<{ bytes: Uint8Array }>();
</script>
<template>
<DocxEditor
:document="bytes"
title="Q3 Memo"
mode="view"
:navigation="false"
/>
</template>The React equivalent sets the same names:
import { DocxEditor } from '@docx-editor.dev/react';
import '@docx-editor.dev/core/styles/editor.css';
export function Viewer({ bytes }: { bytes: Uint8Array }) {
return (
<DocxEditor
document={bytes}
title="Q3 Memo"
mode="view"
navigation={false}
/>
);
}One difference is the stylesheet path. React documents @docx-editor.dev/core/styles/editor.css. Vue re-exports the same file as @docx-editor.dev/vue/styles.css.
Compare composables and hooks
Both adapters export the same helpers from the package root. Neither uses a /hooks or /composables subpath.
The shared set covers 36 names, including:
| Purpose | Name |
|---|---|
| Read the editor instance | useDocxEditor |
| Read editor state | useEditorState, useEditorSnapshot, useEditorCaret |
| Run a command | useEditorCommand, useEditorValueCommand |
| Subscribe to events | useEditorEvent |
| Page and paragraph setup | usePageSetup, useParagraphIndent, useParagraphStyle |
| Fonts and zoom | useFontFamily, useFonts, useZoom |
| Navigation and search | useDocumentOutline, useDocumentSearch, useNavigationPane |
| Content controls | useContentControl, useContentControlInstance |
React exports one name Vue does not: useProvidedDocxEditor. Every other helper has the same name in both adapters.
A toolbar button uses the same command API in both adapters. The Vue component uses this code:
<script setup lang="ts">
import { useEditorCommand } from '@docx-editor.dev/vue';
const bold = useEditorCommand('text.bold');
</script>
<template>
<button
@mousedown.prevent
:disabled="!bold.isEnabled.value"
:aria-pressed="bold.isActive.value"
:title="bold.disabledReason.value ?? 'Bold'"
@click="bold.execute()"
>
Bold
</button>
</template>Call the composable from a component rendered inside <DocxEditorRoot>. The composable accesses the editor through Vue provide/inject, so the component must be in that tree.
useEditorCommand returns execute plus three ComputedRef values. Vue unwraps only top-level refs in a template, and these sit on a returned object, so read them with .value. Writing bold.isEnabled gives the ref itself, which is always truthy.
Template refs instead of a ref object
React passes ref to the component and reads ref.current. Vue names the ref in the template and reads .value.
<script setup lang="ts">
import { ref } from 'vue';
import { DocxEditor, type DocxEditorRef } from '@docx-editor.dev/vue';
defineProps<{ bytes: Uint8Array }>();
const editorRef = ref<DocxEditorRef | null>(null);
async function save() {
const buffer = await editorRef.value?.save();
if (!buffer) return;
await fetch('/api/documents/1', { method: 'PUT', body: buffer });
}
</script>
<template>
<button @click="save">Save</button>
<DocxEditor ref="editorRef" :document="bytes" />
</template>DocxEditorRef exposes the same seven members in both adapters:
| Member | Returns |
|---|---|
load(document) | void |
save() | Promise<ArrayBuffer | null> |
getDocumentHandle() | DocumentHandle | null |
getEditor() | Editor | null |
focus() | void |
exec(command, options?) | ExecResult |
snapshot(options?) | EditorSnapshot |
The ref exposes only these seven members. Use getEditor() to access the full facade.
Events instead of callback props
React's onFoo callback props become Vue events on <DocxEditorRoot>. There are three:
| React prop | Vue event | Payload |
|---|---|---|
onReady | @ready | Editor |
onChange | @change | DocumentChange |
onFontError | @font-error | EditorFontError |
<script setup lang="ts">
import {
DocxEditorContent,
DocxEditorRoot,
DocxEditorViewport,
} from '@docx-editor.dev/vue';
import type { DocumentChange } from '@docx-editor.dev/core';
defineProps<{ bytes: Uint8Array }>();
function onChange(change: DocumentChange) {
console.log('document changed', change);
}
</script>
<template>
<DocxEditorRoot :document="bytes" @change="onChange">
<DocxEditorViewport>
<DocxEditorContent />
</DocxEditorViewport>
</DocxEditorRoot>
</template>Compose the chrome from parts
Both adapters expose the same parts. React nests them under the DocxEditor namespace, such as DocxEditor.Root. Vue imports them as top-level components:
<script setup lang="ts">
import {
DocxEditorContent,
DocxEditorRoot,
DocxEditorToolbar,
DocxEditorViewport,
} from '@docx-editor.dev/vue';
defineProps<{ bytes: Uint8Array }>();
</script>
<template>
<DocxEditorRoot :document="bytes">
<DocxEditorToolbar />
<DocxEditorViewport>
<DocxEditorContent />
</DocxEditorViewport>
</DocxEditorRoot>
</template>Use the packaged <DocxEditor> when you need its default chrome. Compose parts for a custom layout or the Pro review rail.
Where to go next
- Vue DOCX editor covers installation, loading, saving, review features, and localization.
- React Word editor covers the equivalent React workflow.
- Vue package overview describes the full surface.
- Vue composition covers building custom chrome.
- Vue composables documents each helper.
- Vue props reference documents every prop.
- Vue API reference is generated from the type declarations.
