💚 Vue.js Integration Guide

Use Kria Lite WYSIWYG Editor in Vue

Learn how to integrate the lightweight Kria Lite WYSIWYG editor into your Vue.js application. This guide covers Vue 3 Composition API, Options API, and TypeScript support.

⏱️ Time: 5 minutes
📦 Size: ~6KB added
📚 Level: Beginner

📋 Prerequisites

  • Vue 3.x (Vue 2 with minor adjustments)
  • Node.js and npm/yarn installed
  • Basic understanding of Vue components
1

Installation

Install Kria Lite WYSIWYG editor using your preferred package manager:

# Using npm npm install kria-lite # Using yarn yarn add kria-lite # Using pnpm pnpm add kria-lite
2

Vue 3 Composition API

Here's how to use Kria Lite with Vue 3's Composition API:

<!-- KriaEditor.vue --> <template> <div class="kria-editor"> <textarea ref="editorRef"></textarea> </div> </template> <script setup> import { ref, onMounted, onBeforeUnmount } from 'vue' import { WYSIWYG } from 'kria-lite' import 'kria-lite/dist/kria.editor.css' const props = defineProps({ modelValue: { type: String, default: '' }, placeholder: { type: String, default: 'Start writing...' }, height: { type: String, default: '300px' } }) const emit = defineEmits(['update:modelValue']) const editorRef = ref(null) let editorInstance = null onMounted(() => { if (editorRef.value) { editorInstance = WYSIWYG.init(editorRef.value, { height: props.height, placeholder: props.placeholder, onChange: (content) => { emit('update:modelValue', content) } }) // Set initial content if (props.modelValue) { editorInstance.setContent(props.modelValue) } } }) onBeforeUnmount(() => { if (editorInstance) { editorInstance.destroy() editorInstance = null } }) // Expose methods for parent components defineExpose({ getContent: () => editorInstance?.getContent(), setContent: (html) => editorInstance?.setContent(html), focus: () => editorInstance?.focus() }) </script>

Use the component with v-model:

<template> <div> <KriaEditor v-model="content" placeholder="Write your post..." /> <button @click="save">Save</button> </div> </template> <script setup> import { ref } from 'vue' import KriaEditor from './components/KriaEditor.vue' const content = ref('<p>Initial content</p>') function save() { console.log('Saving:', content.value) // Save to your backend } </script>
3

Options API (Vue 2/3)

If you prefer the Options API or need Vue 2 compatibility:

<!-- KriaEditor.vue --> <template> <div class="kria-editor"> <textarea ref="editor"></textarea> </div> </template> <script> import { WYSIWYG } from 'kria-lite' import 'kria-lite/dist/kria.editor.css' export default { name: 'KriaEditor', props: { value: { type: String, default: '' }, placeholder: { type: String, default: 'Start writing...' } }, data() { return { editorInstance: null } }, mounted() { this.editorInstance = WYSIWYG.init(this.$refs.editor, { placeholder: this.placeholder, onChange: (content) => { this.$emit('input', content) } }) if (this.value) { this.editorInstance.setContent(this.value) } }, beforeDestroy() { if (this.editorInstance) { this.editorInstance.destroy() } }, watch: { value(newVal) { const currentContent = this.editorInstance?.getContent() if (currentContent !== newVal) { this.editorInstance?.setContent(newVal) } } }, methods: { getContent() { return this.editorInstance?.getContent() }, focus() { this.editorInstance?.focus() } } } </script>
4

Reusable Composable

Create a reusable composable for the editor logic:

// composables/useKriaEditor.js import { ref, onMounted, onBeforeUnmount } from 'vue' import { WYSIWYG } from 'kria-lite' export function useKriaEditor(options = {}) { const editorRef = ref(null) let instance = null onMounted(() => { if (editorRef.value) { instance = WYSIWYG.init(editorRef.value, { height: '300px', ...options }) } }) onBeforeUnmount(() => { instance?.destroy() instance = null }) const getContent = () => instance?.getContent() || '' const setContent = (html) => instance?.setContent(html) const focus = () => instance?.focus() return { editorRef, getContent, setContent, focus } }

Use the composable:

<script setup> import { useKriaEditor } from '@/composables/useKriaEditor' const { editorRef, getContent, setContent } = useKriaEditor({ placeholder: 'Write something...', imageUploadUrl: '/api/upload' }) function handleSave() { const content = getContent() console.log('Content:', content) } </script> <template> <textarea ref="editorRef"></textarea> <button @click="handleSave">Save</button> </template>
5

Full v-model Support

A complete component with two-way binding and watchers:

<script setup> import { ref, watch, onMounted, onBeforeUnmount } from 'vue' import { WYSIWYG } from 'kria-lite' const props = defineProps({ modelValue: String }) const emit = defineEmits(['update:modelValue']) const editorRef = ref(null) let instance = null let isInternalChange = false onMounted(() => { instance = WYSIWYG.init(editorRef.value, { onChange: (content) => { isInternalChange = true emit('update:modelValue', content) nextTick(() => { isInternalChange = false }) } }) if (props.modelValue) { instance.setContent(props.modelValue) } }) // Watch for external changes watch(() => props.modelValue, (newVal) => { if (!isInternalChange && instance) { const current = instance.getContent() if (current !== newVal) { instance.setContent(newVal || '') } } }) onBeforeUnmount(() => { instance?.destroy() }) </script>
6

TypeScript Support

Fully typed composable for TypeScript projects:

// composables/useKriaEditor.ts import { ref, onMounted, onBeforeUnmount, Ref } from 'vue' import { WYSIWYG, EditorOptions, EditorInstance } from 'kria-lite' interface UseKriaEditorReturn { editorRef: Ref<HTMLTextAreaElement | null> getContent: () => string setContent: (html: string) => void focus: () => void } export function useKriaEditor( options: Partial<EditorOptions> = {} ): UseKriaEditorReturn { const editorRef = ref<HTMLTextAreaElement | null>(null) let instance: EditorInstance | null = null onMounted(() => { if (editorRef.value) { instance = WYSIWYG.init(editorRef.value, options) } }) onBeforeUnmount(() => { instance?.destroy() instance = null }) return { editorRef, getContent: () => instance?.getContent() ?? '', setContent: (html: string) => instance?.setContent(html), focus: () => instance?.focus() } }
7

Nuxt.js Integration

For Nuxt.js, use client-only rendering since Kria Lite requires DOM:

<!-- components/KriaEditor.client.vue --> <!-- The .client.vue suffix ensures client-only rendering in Nuxt 3 --> <template> <textarea ref="editorRef"></textarea> </template> <script setup> import { useKriaEditor } from '@/composables/useKriaEditor' const props = defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) const { editorRef } = useKriaEditor({ onChange: (content) => emit('update:modelValue', content) }) </script>

Or use the ClientOnly wrapper:

<template> <ClientOnly> <KriaEditor v-model="content" /> <template #fallback> <div class="h-[300px] bg-gray-100 animate-pulse"></div> </template> </ClientOnly> </template>
8

Best Practices

✅ Do: Use onBeforeUnmount for cleanup

Always destroy the editor instance to prevent memory leaks, especially in SPAs where components mount/unmount frequently.

✅ Do: Lazy load the editor

Use defineAsyncComponent to load the editor only when needed.

❌ Don't: Initialize in reactive

Don't make the editor instance reactive (ref/reactive). Store it as a plain variable to avoid unnecessary re-renders.

Next Steps

You now have Kria Lite WYSIWYG editor running in your Vue.js application!