Refactor QuillyEditor and Quill Mention Extension for Improved Functionality
- Updated `QuillyEditor.vue` to enhance the handling of model updates and internal changes, ensuring better synchronization between the editor and the model value. Introduced a new `pasteHTML` function to manage HTML content pasting more effectively. - Refactored `quillMentionExtension.js` to improve the processing of pasted content, ensuring that only valid mentions are retained and transforming flat mention structures into nested ones for better data integrity. - Enhanced the SCSS styles in `app.scss` to apply list styles to ordered and unordered lists within the `.field-help` class, improving the visual presentation of help text. These changes aim to improve the overall functionality, maintainability, and user experience of the QuillyEditor component and its associated mention extension.
This commit is contained in:
@@ -5,94 +5,107 @@
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Quill from 'quill'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import { onMounted, onBeforeUnmount, ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'update:modelValue',
|
||||
'text-change',
|
||||
'selection-change',
|
||||
'editor-change',
|
||||
'blur',
|
||||
'focus',
|
||||
'ready'
|
||||
])
|
||||
|
||||
let quillInstance = null
|
||||
const container = ref(null)
|
||||
let isInternalChange = false
|
||||
|
||||
const setContents = (content) => {
|
||||
if (!quillInstance) return
|
||||
|
||||
isInternalChange = true
|
||||
quillInstance.root.innerHTML = content
|
||||
quillInstance.update()
|
||||
isInternalChange = false
|
||||
<script setup>
|
||||
import Quill from 'quill'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import { onMounted, onBeforeUnmount, ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
|
||||
const initializeQuill = () => {
|
||||
if (container.value) {
|
||||
quillInstance = new Quill(container.value, props.options)
|
||||
|
||||
quillInstance.on('selection-change', (range, oldRange, source) => {
|
||||
if (!range) {
|
||||
emit('blur', quillInstance)
|
||||
} else {
|
||||
emit('focus', quillInstance)
|
||||
}
|
||||
emit('selection-change', { range, oldRange, source })
|
||||
})
|
||||
|
||||
quillInstance.on('text-change', (delta, oldContents, source) => {
|
||||
if (!isInternalChange) {
|
||||
const html = quillInstance.root.innerHTML
|
||||
emit('text-change', { delta, oldContents, source })
|
||||
emit('update:modelValue', html)
|
||||
}
|
||||
})
|
||||
|
||||
quillInstance.on('editor-change', (eventName, ...args) => {
|
||||
emit('editor-change', eventName, ...args)
|
||||
})
|
||||
|
||||
if (props.modelValue) {
|
||||
setContents(props.modelValue)
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'update:modelValue',
|
||||
'text-change',
|
||||
'selection-change',
|
||||
'editor-change',
|
||||
'blur',
|
||||
'focus',
|
||||
'ready'
|
||||
])
|
||||
|
||||
let quillInstance = null
|
||||
const container = ref(null)
|
||||
const model = ref(props.modelValue)
|
||||
|
||||
const pasteHTML = (instance) => {
|
||||
instance.clipboard.dangerouslyPasteHTML(props.modelValue || '', 'silent')
|
||||
}
|
||||
|
||||
const initializeQuill = () => {
|
||||
if (container.value) {
|
||||
quillInstance = new Quill(container.value, props.options)
|
||||
|
||||
quillInstance.on('selection-change', (range, oldRange, source) => {
|
||||
if (!range) {
|
||||
emit('blur', quillInstance)
|
||||
} else {
|
||||
emit('focus', quillInstance)
|
||||
}
|
||||
|
||||
emit('ready', quillInstance)
|
||||
emit('selection-change', { range, oldRange, source })
|
||||
})
|
||||
|
||||
quillInstance.on('text-change', (delta, oldContents, source) => {
|
||||
// Update local model only on user input
|
||||
model.value = quillInstance.getSemanticHTML()
|
||||
emit('text-change', { delta, oldContents, source })
|
||||
})
|
||||
|
||||
quillInstance.on('editor-change', (eventName, ...args) => {
|
||||
emit('editor-change', eventName, ...args)
|
||||
})
|
||||
|
||||
if (props.modelValue) {
|
||||
pasteHTML(quillInstance)
|
||||
model.value = quillInstance.getSemanticHTML()
|
||||
}
|
||||
|
||||
emit('ready', quillInstance)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initializeQuill()
|
||||
})
|
||||
|
||||
// Watch modelValue and paste HTML if has changes
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
if (!quillInstance) return
|
||||
if (newValue && newValue !== model.value) {
|
||||
pasteHTML(quillInstance)
|
||||
model.value = quillInstance.getSemanticHTML()
|
||||
} else if (!newValue) {
|
||||
quillInstance.setContents([])
|
||||
model.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initializeQuill()
|
||||
})
|
||||
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
if (quillInstance && newValue !== quillInstance.root.innerHTML) {
|
||||
setContents(newValue || '')
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (quillInstance) {
|
||||
quillInstance.off('selection-change')
|
||||
quillInstance.off('text-change')
|
||||
quillInstance.off('editor-change')
|
||||
}
|
||||
quillInstance = null
|
||||
})
|
||||
</script>
|
||||
)
|
||||
|
||||
// Watch model and update modelValue if has changes
|
||||
watch(model, (newValue, oldValue) => {
|
||||
if (!quillInstance) return
|
||||
if (newValue && newValue !== oldValue) {
|
||||
emit('update:modelValue', newValue)
|
||||
} else if (!newValue) {
|
||||
quillInstance.setContents([])
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (quillInstance) {
|
||||
quillInstance.off('selection-change')
|
||||
quillInstance.off('text-change')
|
||||
quillInstance.off('editor-change')
|
||||
}
|
||||
quillInstance = null
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user