Vue3 + wangeditor 5.x 保姆级教程:从封装组件到图片视频上传(附完整代码)
Vue3 wangeditor 5.x 企业级封装实战打造高可用的富文本上传组件在后台管理系统开发中富文本编辑器几乎是标配功能。但市面上大多数教程只停留在基础API调用层面对于实际企业开发中遇到的样式污染、上传接口对接、组件销毁等痛点问题往往避而不谈。本文将基于Vue3的组合式API带你从零封装一个生产环境可用的wangeditor组件重点解决以下问题如何实现图片/视频的自定义上传逻辑组件样式隔离的最佳实践方案内存泄漏防范与编辑器实例销毁支持双向绑定的v-model集成上传进度反馈与错误处理机制1. 环境准备与基础集成1.1 初始化项目与安装依赖首先确保你的项目已经配置好Vue3环境。推荐使用Vite作为构建工具npm create vitelatest vue3-editor-demo --template vue-ts安装wangeditor相关依赖npm install wangeditor/editor wangeditor/editor-for-vue1.2 基础组件结构创建src/components/RichEditor.vue文件搭建基础骨架template div classeditor-container Toolbar :editoreditorRef :defaultConfigtoolbarConfig modedefault / Editor v-modelmodelValue :defaultConfigeditorConfig modedefault onCreatedhandleCreated / /div /template script setup langts import wangeditor/editor/dist/css/style.css import { onBeforeUnmount, shallowRef } from vue import { Editor, Toolbar } from wangeditor/editor-for-vue const editorRef shallowRef() const modelValue defineModelstring({ required: true }) const handleCreated (editor: any) { editorRef.value editor } /script关键点说明使用shallowRef存储编辑器实例可以避免不必要的响应式开销这对富文本这种复杂对象尤为重要。2. 深度配置编辑器功能2.1 工具栏定制化wangeditor支持高度自定义的工具栏配置。以下是企业应用中常见的配置方案const toolbarConfig { excludeKeys: [ group-video, // 初始隐藏视频功能 fullScreen, insertLink, codeBlock ], insertKeys: { index: 5, keys: [uploadImage, uploadVideo] } }2.2 编辑器核心配置针对不同场景我们需要灵活调整编辑器的行为const editorConfig { placeholder: 请输入内容..., autoFocus: false, scroll: true, maxLength: 50000, MENU_CONF: {} }3. 实现文件上传功能3.1 图片上传方案企业级应用通常需要对接自己的文件服务下面是一个完整的图片上传实现editorConfig.MENU_CONF[uploadImage] { fieldName: file, server: /api/upload/image, maxFileSize: 5 * 1024 * 1024, // 5MB allowedFileTypes: [image/*], customUpload: async (file: File, insertFn: Function) { try { const formData new FormData() formData.append(file, file) const { data } await axios.post(/api/upload, formData, { headers: { Content-Type: multipart/form-data }, onUploadProgress: (progressEvent) { const percent Math.round( (progressEvent.loaded * 100) / progressEvent.total ) // 可以在这里添加进度显示逻辑 } }) insertFn(data.url, , ) } catch (error) { console.error(上传失败:, error) // 添加错误提示逻辑 } } }3.2 视频上传的特殊处理视频上传需要额外考虑封面和预览问题editorConfig.MENU_CONF[uploadVideo] { customUpload: async (file: File, insertFn: Function) { // 先上传视频文件 const videoRes await uploadFile(file) // 生成视频封面缩略图 const poster await generateVideoPoster(videoRes.url) insertFn(videoRes.url, poster) } }4. 生产环境优化策略4.1 样式隔离方案避免编辑器样式影响全局样式.editor-container { :deep(.w-e-bar) { background-color: #f8f8f8; border: 1px solid #ddd; } :deep(.w-e-text-container) { border: 1px solid #ddd !important; border-top: none !important; } }4.2 内存管理与性能优化正确处理组件销毁onBeforeUnmount(() { const editor editorRef.value if (!editor) return editor.destroy() editorRef.value null })4.3 扩展功能集成实现字数统计功能示例const handleChange (editor: IDomEditor) { const text editor.getText() const html editor.getHtml() // 触发字数变化事件 emit(count-change, { textLength: text.length, htmlLength: html?.length || 0 }) }5. 完整组件代码与使用示例5.1 最终组件实现template div classrich-editor Toolbar :editoreditorRef :defaultConfigtoolbarConfig / Editor v-modelmodelValue :defaultConfigeditorConfig onCreatedhandleCreated onChangehandleChange / div v-ifshowCount classeditor-count 字数: {{ count }} / {{ maxLength }} /div /div /template script setup langts // 完整导入和配置见上文实现 /script style scoped langscss // 完整样式见上文实现 /style5.2 在父组件中使用template RichEditor v-modelcontent :maxLength10000 count-changehandleCountChange / /template script setup const content ref(p初始内容/p) const handleCountChange ({ textLength }) { console.log(当前字数:, textLength) } /script在实际项目中这个组件已经处理了文件上传、样式隔离、内存管理等企业级关注点可以直接集成到你的后台系统中。根据具体需求你还可以进一步扩展如粘贴图片自动上传、自定义表情面板等功能。