如何将原生JavaScript实现的CKEditor4功能改写为Vue3自定义组件
原生JS实现的CKEditor4功能迁移为Vue3组件解决方案
现有代码错误点
- CKEditor 4不是Vue专属插件,不能使用
myApp.use()方法注册,该方法仅支持Vue插件安装,原有全局注册逻辑错误 CKEDITOR.replace()第一个参数要求传入textarea的ID字符串或者真实DOM元素,原有代码传入了Vue的ref对象本身,未取ref.value指向的真实DOM,导致CKEditor找不到要替换的目标元素- 上传配置的
_token参数未赋值真实的Laravel CSRF令牌,后续上传功能会报错
修复步骤
步骤1:修正CKEditor引入方式
不需要使用依赖注入,直接将CKEditor挂载到全局window对象即可,和原生引入行为一致:
// 原有全局注册代码修改 import CKEDITOR from '../../js/Librairies/ckeditor-4-6-2'; // 直接挂载到window,不需要用app.use注册 window.CKEDITOR = CKEDITOR; let myApp = createApp({ render: () => h(app, props) }); // 删掉 myApp.use(CKEDITOR, 'CKEDITOR') 这一行
你也可以直接在项目入口HTML文件中引入CKEditor的CDN,和原生实现保持一致,更简单:
<!-- 放在index.html的body末尾 --> <script src="//cdn.ckeditor.com/4.6.2/standard/ckeditor.js"></script>
步骤2:修正CKEditor组件代码
<template> <div> <textarea ref="editor"></textarea> </div> </template> <script> import { onMounted, ref, watch } from 'vue'; export default { name: 'TextareaCkEditor', // 支持v-model双向绑定 props: { modelValue: { type: String, default: '' } }, emits: ['update:modelValue'], setup(props, { emit }) { const editor = ref(null); let ckEditorInstance = null; onMounted(() => { // 传入ref指向的真实DOM元素 ckEditorInstance = window.CKEDITOR.replace(editor.value, { filebrowserImageBrowseUrl: '/laravel-filemanager?type=Images', // 拼接真实CSRF令牌 filebrowserImageUploadUrl: '/laravel-filemanager/upload?type=Images&_token=' + document.querySelector('meta[name="csrf-token"]').content, filebrowserBrowseUrl: '/laravel-filemanager?type=Files', filebrowserUploadUrl: '/laravel-filemanager/upload?type=Files&_token=' + document.querySelector('meta[name="csrf-token"]').content }); // 监听编辑器内容变化,同步到父组件v-model ckEditorInstance.on('change', () => { emit('update:modelValue', ckEditorInstance.getData()); }); // 初始内容赋值 ckEditorInstance.setData(props.modelValue); }) // 监听父组件传入内容变化,同步到编辑器 watch(() => props.modelValue, (newVal) => { if (ckEditorInstance && newVal !== ckEditorInstance.getData()) { ckEditorInstance.setData(newVal); } }) return { editor } } } </script>
步骤3:组件使用示例
<template> <div> <TextareaCkEditor v-model="editorContent" /> </div> </template> <script> import TextareaCkEditor from './TextareaCkEditor.vue' export default { components: { TextareaCkEditor }, data() { return { editorContent: 'test editor content' } } } </script>
内容的提问来源于stack exchange,提问作者Jérémie Chazelle
相关产品推荐
相关产品推荐

