ckeditor官方提供了开箱即用的vue组件,但是其功能很有限,如果只是希望简单使用可以用此组件。如果需要更复杂的功能,则需要自己定义。
官方地址文档:https://ckeditor.com/docs/ckeditor5/latest/installation/frameworks/vuejs-v3.html
1.在线定义
进入https://ckeditor.com/ckeditor-5/online-builder/,选择
选择功能
2.打包使用ckeditor文件
下载的文件解压后或得到一个webpack项目,你可以自己在其中新增功能,在打包使用,或者直接使用
3.添加额外功能
比如添加控制文本位置插件,先在此项目中安装插件
npm install @ckeditor/ckeditor5-autoformat --save-dev
在ckeditor.js引入
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat.js';
Editor.builtinPlugins = [
Alignment,
.... 其他插件
]
Editor.defaultConfig = {
toolbar: {// 控制工具栏显示
items: [
'heading',
'htmlEmbed',
'|',
'alignment',
... 其他忽略
]
}
}
这样操作就可显示控制文本位置的图标
4.自定义插件
自己定义插件,你需要先安装下方依赖
npm install @ckeditor/ckeditor5-ui @ckeditor/ckeditor5-core --save-dev
如自定义一个上传图片按钮
import { Plugin, icons } from '@ckeditor/ckeditor5-core';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
class UploadImage extends Plugin {
init() {
const editor = this.editor;
// The button must be registered among the UI components of the editor
// to be displayed in the toolbar.
editor.ui.componentFactory.add( 'customUploadImage', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set( {
label: '上传图片',
withText: true,
class: 'custom-upload-image',
icon: icons.image,
} );
// // 执行
// button.on('execute', () => {
// console.log("执行了...")
// });
return button;
} );
}
}
Editor.builtinPlugins = [UploadImage, ]
Editor.defaultConfig = {
toolbar: {
items: ['customUploadImage']
}
}
在npm run build打包就可以显示出来
5. 封装Vue组件
引入打包的ckeditor.js,将整个build复制到项目的public,可以删除其中的部分翻译文件,保留中英文js文件即可,在index.html引入ckeditor.js
<template>
<div style="width: 100%">
<div class="editor"></div>
</div>
</template>
<script lang="ts" setup>
import { markRaw, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue"
import { FileService } from "@/components/FileService"
import { debounce } from "@/utils/common"
const props = defineProps({
modelValue: {
type: String,
default: "",
},
})
const lastEditorData = ref("") // 上一次编辑数据
const emit = defineEmits(["update:modelValue"])
const editorRef = ref()
const showUploadImageDialog = () => {
const customUploadImageEle = document.querySelector(".custom-upload-image") as HTMLElement
if (customUploadImageEle) {
customUploadImageEle.addEventListener("click", () => {
FileService.show({
handleOk: (files) => {
const src = files[0].url
const htmlDP = editorRef.value.data.processor
const viewFragment = htmlDP.toView(`<img src="${src}" alt="" />`)
const modelFragment = editorRef.value.data.toModel(viewFragment)
editorRef.value.model.insertContent(modelFragment)
},
})
})
}
}
// 设置html
const setHtml = (v: string) => {
return editorRef.value.setData(v)
}
watch(
() => props.modelValue,
(newVal: any) => {
if (editorRef.value && newVal !== lastEditorData.value) {
setHtml(newVal)
}
}
)
// 获取html
const getHtml = () => {
return editorRef.value.getData()
}
const renderCkEditor = () => {
;(window as any).ClassicEditor.create(document.querySelector(".editor"), {
toolbar: {
shouldNotGroupWhenFull: true, // 当宽度超出时,换行显示工具栏
},
htmlSupport: {
allow: [
// Enables all HTML features.
{
name: /.*/,
attributes: true,
classes: true,
styles: true,
},
],
disallow: [
{
attributes: [{ key: /.*/, value: /data:(?!image\/(png|jpeg|gif|webp))/i }],
},
],
},
})
.then((editor: any) => {
editorRef.value = markRaw(editor)
nextTick(() => {
showUploadImageDialog()
const emitDebouncedInputEvent = debounce((evt: any) => {
const data = (lastEditorData.value = editorRef.value.getData())
emit("update:modelValue", data)
}, 300)
editorRef.value.model.document.on("change:data", emitDebouncedInputEvent)
})
})
.catch((error: any) => {
console.error(error)
})
}
onMounted(() => {
renderCkEditor()
})
onBeforeUnmount(() => {
if (editorRef.value) {
// 销毁组件
setHtml("")
editorRef.value.destroy()
}
})
defineExpose({ editorRef, getHtml, setHtml })
</script>
<style lang="scss" scoped>
:deep(.ck-editor__editable) {
height: 600px;
//overflow-y: scroll;
}
</style>
评论列表
已有0条评论