用来用去还是用回了ueditor-Vue富文本编辑器二次扩展。我们使用用过UEditor、TinyMCE、CKEditor、wangEditor、Tiptap、Quill项目经历过多次富文本的编辑器的选型使用,发现现在新的富文本编辑总感觉还是没达到我们的要求,果然改回了ueditor。
UEditor 是由百度WEB前端研发部开发的一款所见即所得的开源富文本编辑器。它具有轻量、可定制、用户体验优秀等特点,并且基于MIT开源协议(也有说法是基于BSD协议),所有源代码在协议允许范围内可自由修改和使用。UEditor的推出,有效降低了网站开发者的开发成本,节约了他们在开发富文本编辑器方面所需的大量时间。
一、系统特点
分层架构设计:UEditor在设计上采用了经典的分层架构设计理念,包括核心层、命令插件层和UI层,以实现功能层次之间的轻度耦合。
核心层:提供编辑器底层的方法和概念,如DOM树操作、Selection、Range等。
命令插件层:所有的功能型实现都通过这一层中的命令和插件来完成,各个命令和插件之间基本互不耦合,方便定制与扩展。
UI层:与核心层和命令插件层几乎完全解耦,简单的配置即可为编辑器在界面上添加额外的UI元素和功能。
二、优点
体积小巧,性能优良:UEditor在保证功能全面的同时,尽量减少了体积,提升了性能。
使用简单:对于开发者来说,UEditor易于上手,可以快速集成到项目中。
多浏览器支持:支持Mozilla、MSIE、FireFox、Maxthon、Safari和Chrome等多种浏览器。
丰富完善的中文文档:为开发者提供了详尽的中文文档,方便学习和使用。
vue-ueditor-wrap 是一个Vue组件,它封装了UEditor(百度富文本编辑器)以便更容易地在Vue项目中集成和使用。UEditor是一个功能强大的富文本编辑器,但直接将其集成到Vue项目中可能会遇到一些兼容性和维护性的问题,而vue-ueditor-wrap正是为了解决这些问题而设计的。
如何使用 vue-ueditor-wrap
bash复制代码
npm install vue-ueditor-wrap --save
或者
bash复制代码
yarn add vue-ueditor-wrap
扩展组件
接下来,在你的Vue组件中引入vue-ueditor-wrap。
<template> <div style="border: 1px solid #ccc"> <vue-ueditor-wrap v-model="data" :config="editorConfig" :editorDependencies="['ueditor.config.js', 'ueditor.all.js']" ref="editorRef" ></vue-ueditor-wrap> <diy-storage ref="storageImg" style="display: none" @confirm="getAttachmentFileList"></diy-storage> <diy-storage ref="storageVideo" type="video" accept=".rm,.rmvb,.wmv,.avi,.mpg,.mpeg,.mp4" style="display: none" @confirm="getAttachmentVideoFileList" ></diy-storage> </div> </template> <script setup name="DiyEditor"> import { ref } from 'vue'; import { VueUeditorWrap } from 'vue-ueditor-wrap'; import { useVModel } from '@vueuse/core'; import DiyStorage from '@/components/upload/storage.vue'; import { Session } from '@/utils/storage'; const editorRef = ref(); const storageImg = ref(null); const storageVideo = ref(null); const props = defineProps({ modelValue: { type: String, default: '', }, height: { type: Number, default: 300, }, }); const emit = defineEmits(['update:modelValue', 'handleBlur']); const data = useVModel(props, 'modelValue', emit); const serverHeaders = { Authorization: Session.get('token'), }; const editorConfig = ref({ debug: false, UEDITOR_HOME_URL: import.meta.env.MODE == 'development' ? '/public/ueditor/' : import.meta.env.VITE_BUILD_DIR + '/ueditor/', serverUrl: (process.env.NODE_ENV === 'production' ? '' : '/api') + '/sys/storage/upload', serverHeaders, // 编辑器不自动被内容撑高 autoHeightEnabled: false, // 初始容器高度 initialFrameHeight: props.height, // 初始容器宽度 initialFrameWidth: '100%', toolbarCallback: function (cmd, editor) { editorRef.value = editor; if (cmd == 'insertimage') { storageImg.value.handleStorageDlg('', '上传图片'); return true; } else if (cmd == 'insertvideo') { storageVideo.value.handleStorageDlg('', '上传视频'); return true; } }, }); const getAttachmentFileList = (files) => { if (!files.length) { return; } files.forEach((element) => { editorRef.value?.execCommand('insertHtml', "<img src='" + element.url + "'/>"); }); }; const getAttachmentVideoFileList = (files) => { if (!files.length) { return; } files.forEach((element) => { editorRef.value?.execCommand('insertHtml', "<video src='" + element.url + "'/>"); }); }; </script>
- 注意:v-model用于双向绑定编辑器的内容,config属性用于传递UEditor的配置选项。
配置UEditor
- 你可以通过:config属性向vue-ueditor-wrap传递UEditor的配置选项。这些选项会直接影响编辑器的行为和外观。UEditor提供了大量的配置项,你可以根据自己的需求进行调整。
注意事项
确保你已经按照vue-ueditor-wrap的文档和UEditor的官方文档正确配置了编辑器。
如果你在Vue CLI项目中工作,可能需要处理静态资源(如UEditor的JS和CSS文件)的路径问题。
vue-ueditor-wrap可能会随着版本的更新而发生变化,因此建议查阅最新的文档和更新日志。
调试和测试
在集成vue-ueditor-wrap之后,你应该在多个浏览器和设备上测试你的Vue应用,以确保编辑器能够正常工作并且符合你的要求。
- 组件调用实现
<template> <div class="container"> <div class="flex diygw-col-24"> <el-form-item prop="editor" class="diygw-el-rate" label="多行输入" label-width="80px"> <diy-editor v-model="editor"></diy-editor> </el-form-item> </div> <div class="clearfix"></div> </div> </template> <script> import { useRouter, useRoute } from 'vue-router'; import { storeToRefs } from 'pinia'; import { useUserInfo } from '@/stores/userInfo'; import { ElMessageBox, ElMessage } from 'element-plus'; import DiyEditor from '@/components/editor/index.vue'; export default { components: { DiyEditor }, data() { return { globalOption: {}, userInfo: {}, roleDatas: { rows: [ { status: '', flag: '', remark: '', roleId: 0, roleName: '', roleKey: '', dataScope: '', roleSort: 0, createTime: '', updateTime: '', deleteTime: null, userId: null, updateUserId: null } ], total: 0, code: 0, msg: '' }, editor: '' }; }, methods: { getParamData(e, row) { row = row || {}; let dataset = e.currentTarget ? e.currentTarget.dataset : e; if (row) { dataset = Object.assign(dataset, row); } return dataset; }, navigateTo(e, row) { let dataset = this.getParamData(e, row); let { type } = dataset; if (type == 'page' || type == 'inner' || type == 'href') { this.router.push({ path: dataset.url, query: dataset }); } else if (typeof this[type] == 'function') { this[type](dataset); } else { ElMessage.error('待实现点击事件'); } }, async init() {}, // 新增接口 API请求方法 async roleDatasApi(param, data) { param = param || {}; param = this.getParamData(param); let http_url = '/sys/role/all'; let http_data = { tt: param.tt || '1', te: param.te || this.t523 || '123' }; let http_header = { 'Content-Type': 'application/json', 'Content-Length': '123' }; let roleDatas = await this.$http.post(http_url, http_data, http_header, 'json'); this.roleDatas = roleDatas; } }, async mounted() { this.router = useRouter(); this.globalOption = useRoute().query; const stores = useUserInfo(); const { userInfos } = storeToRefs(stores); this.userInfo = userInfos; await this.init(); }, beforeUnmount() {} }; </script> <style lang="scss" scoped> .container { font-size: 12px; } </style>
通过使用vue-ueditor-wrap,你可以轻松地将UEditor集成到你的Vue项目中,从而为用户提供一个功能丰富的文本编辑体验。
扩展组件代码已开源至https://gitee.com/diygw/diygw-ui-admin
大家可以前往下载