Skip to content

Instantly share code, notes, and snippets.

@Sonic853
Last active April 13, 2023 07:32
Show Gist options
  • Save Sonic853/ceb5b668f8362b0c760e066c60509e50 to your computer and use it in GitHub Desktop.
Save Sonic853/ceb5b668f8362b0c760e066c60509e50 to your computer and use it in GitHub Desktop.
基于 vue Component 组建的 Vditor
<script setup lang="ts">
import { onMounted, ref, watch, toRaw, computed, defineComponent, h, Ref } from 'vue'
import type { PropType } from 'vue'
import "vditor/dist/index.css"
import Vditor from "vditor"
const simpleConfig = [
'emoji',
'headings',
'bold',
'italic',
'strike',
'link',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'table'
]
const mobileConfig = [
'emoji',
'link',
'upload',
'edit-mode',
{
name: 'more',
toolbar: ['insert-after', 'fullscreen', 'preview']
}
]
const defaultConfig = [
'emoji',
'headings',
'bold',
'italic',
'strike',
'link',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'upload',
'record',
'table',
'|',
'undo',
'redo',
'|',
'fullscreen',
'edit-mode',
'|',
'content-theme',
'code-theme',
{
name: 'more',
toolbar: ['both', 'export', 'outline', 'preview', 'devtools']
}
]
const emit = defineEmits(['update:modelValue', 'after', 'focus', 'blur', 'esc', 'ctrlEnter', 'select'])
const props = defineProps({
mode: {
type: String as PropType<'simple' | 'full' | 'mobile'>,
default: 'full'
},
options: {
type: Object as PropType<IOptions>,
default: () => { }
},
modelValue: {
type: String,
default: ''
}
})
// 创建随机字符串
function randomStr() {
// return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
return 'xxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}
const options = {
simple: simpleConfig,
full: defaultConfig,
mobile: mobileConfig
}
let editorId = 'vue-vditor-' + randomStr()
const contentEditor = ref<Vditor | null>(null)
const editorRef = ref<HTMLElement | null>(null)
const toolbarOptions = computed(() => options[props.mode])
let preview: IPreview = {
actions: ['desktop', 'tablet', 'mobile'],
...(props?.options?.preview || {})
}
onMounted(() => {
contentEditor.value = new Vditor(editorRef.value as HTMLElement, {
toolbar: toolbarOptions.value,
...props.options,
cache: {
...(props?.options?.cache || {}),
id: editorId
},
preview,
value: props.modelValue,
after() {
props?.options?.after?.()
emit('after', toRaw(contentEditor.value))
},
input(value: string) {
props?.options?.input?.(value)
emit('update:modelValue', value)
},
focus(value: string) {
props?.options?.focus?.(value)
emit('focus', value)
},
blur(value: string) {
props?.options?.blur?.(value)
emit('blur', value)
},
esc(value: string) {
props?.options?.esc?.(value)
emit('esc', value)
},
ctrlEnter(value: string) {
props?.options?.ctrlEnter?.(value)
emit('ctrlEnter', value)
},
select(value: string) {
props?.options?.select?.(value)
emit('select', value)
}
})
})
// watch
watch(
() => props.modelValue,
(value) => contentEditor.value?.setValue(value)
)
</script>
<template>
<div ref="editorRef"></div>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment