当前位置: 首页 > news >正文

Vue3 + wangEditor 实战:从封装可复用的富文本组件到图片上传(附完整代码)

Vue3 + wangEditor 深度封装:打造企业级富文本组件与图片上传方案

在当今内容驱动的Web应用中,富文本编辑器已成为不可或缺的核心组件。本文将带您深入探索如何基于Vue3和wangEditor构建一个生产级可复用富文本组件,特别聚焦于开发者最关心的图片上传定制化方案。不同于基础教程,我们将从架构设计角度出发,解决实际业务场景中的复杂问题。

1. 组件化架构设计

1.1 核心Props与Emits设计

一个优秀的富文本组件应该像乐高积木一样灵活可配。以下是经过多个项目验证的props设计方案:

defineProps({ // 初始内容(支持v-model双向绑定) modelValue: { type: String, default: '' }, // 禁用状态 disabled: { type: Boolean, default: false }, // 编辑器高度(支持响应式) height: { type: [String, Number], default: '500px' }, // 自定义工具栏配置 toolbarConfig: { type: Object, default: () => ({}) }, // 上传接口认证头 uploadHeaders: { type: Object, default: () => ({}) } })

对应的emit事件设计:

const emits = defineEmits([ 'update:modelValue', // v-model支持 'upload-start', // 文件上传开始 'upload-success', // 上传成功回调 'upload-error', // 上传错误处理 'editor-mounted' // 编辑器实例就绪 ])

1.2 实例管理的最佳实践

wangEditor实例管理需要特别注意Vue3的响应式特性:

const editorRef = shallowRef() // 必须使用shallowRef const handleCreated = (editor: IDomEditor) => { editorRef.value = editor emits('editor-mounted', editor) // 处理初始禁用状态 if (props.disabled) { editor.disable() } }

关键提示:使用shallowRef而非ref可以避免Vue对编辑器实例的深度响应式代理,这对性能至关重要。

2. 图片上传深度定制

2.1 完整的上传流程封装

图片上传是富文本编辑器中最复杂的业务场景之一。我们需要处理:

  • 文件类型验证
  • 大小限制
  • 多图上传
  • 上传进度反馈
  • 错误处理
const editorConfig = { MENU_CONF: { uploadImage: { maxFileSize: 10 * 1024 * 1024, // 10MB allowedFileTypes: ['image/jpeg', 'image/png', 'image/gif'], customUpload: async (file: File, insertFn: InsertFnType) => { try { emits('upload-start', file) const formData = new FormData() formData.append('file', file) // 添加业务特定参数 formData.append('category', 'editor') const { data } = await axios.post('/api/upload', formData, { headers: { 'Authorization': 'Bearer xxx', ...props.uploadHeaders }, onUploadProgress: (progressEvent) => { // 上传进度反馈 const percent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ) console.log(`上传进度: ${percent}%`) } }) // 插入编辑器 insertFn(data.url, file.name, data.altText) emits('upload-success', data) } catch (error) { emits('upload-error', error) throw new Error('图片上传失败') } } } } }

2.2 企业级解决方案对比

方案类型优点缺点适用场景
直接上传实现简单需处理跨域、认证小型项目
代理上传隐藏真实接口增加服务器负担企业内网
云存储直传减轻服务器压力需要SDK集成公有云项目
分片上传支持大文件实现复杂视频/大型文件

3. 高级功能实现

3.1 内容协同编辑方案

实现多人协同编辑需要特殊处理:

// 在组件中暴露编辑器实例 defineExpose({ getEditorInstance: () => editorRef.value, getContent: () => valueHtml.value, setContent: (html: string) => { valueHtml.value = html } }) // 父组件中使用 const editorComponent = ref() const handleCollaborate = () => { const editor = editorComponent.value.getEditorInstance() editor.disable() // 进入只读模式 }

3.2 内容安全处理

防范XSS攻击的净化方案:

import { clean } from 'xss' const handleChange = (editor: IDomEditor) => { const html = editor.getHtml() const sanitized = clean(html, { whiteList: { a: ['href', 'title', 'target'], img: ['src', 'alt'], // 其他允许的标签和属性... } }) emits('update:modelValue', sanitized) }

4. 性能优化与调试

4.1 内存泄漏防护

编辑器实例必须正确销毁:

onBeforeUnmount(() => { const editor = editorRef.value if (editor && !editor.isDestroyed) { editor.destroy() } })

4.2 按需加载策略

优化包大小的配置方案:

// 在vite.config.js中 export default defineConfig({ optimizeDeps: { include: [ '@wangeditor/editor', '@wangeditor/editor-for-vue' ] } })

5. 完整组件实现

以下是经过生产验证的完整组件代码:

<template> <div class="editor-container"> <Toolbar :editor="editorRef" :defaultConfig="mergedToolbarConfig" /> <Editor v-model="valueHtml" :defaultConfig="editorConfig" @onCreated="handleCreated" @onChange="handleChange" :style="{ height: computedHeight }" /> </div> </template> <script setup> import '@wangeditor/editor/dist/css/style.css' import { Editor, Toolbar } from '@wangeditor/editor-for-vue' import { computed, shallowRef, watch } from 'vue' const props = defineProps({ /* 如前定义 */ }) const emits = defineEmits([ /* 如前定义 */ ]) // 编辑器实例和配置 const editorRef = shallowRef() const valueHtml = ref(props.modelValue) // 计算高度(支持数字和字符串) const computedHeight = computed(() => typeof props.height === 'number' ? `${props.height}px` : props.height ) // 合并工具栏配置 const mergedToolbarConfig = computed(() => ({ toolbarKeys: [ 'headerSelect', 'bold', 'italic', /* 其他默认配置... */ ], ...props.toolbarConfig })) /* 其他方法实现... */ </script> <style> .editor-container { border: 1px solid #ddd; border-radius: 4px; overflow: hidden; } </style>

在实际项目中使用时,这个组件可以轻松集成到各种场景:

<template> <RichTextEditor v-model="content" :upload-headers="authHeaders" @upload-error="handleUploadError" /> </template>

经过多个项目的实践验证,这种封装方案在保持灵活性的同时,提供了企业级应用所需的稳定性和扩展性。特别是在处理图片上传这类复杂场景时,良好的接口设计可以让业务集成变得事半功倍。

http://www.jsqmd.com/news/558268/

相关文章:

  • OpenRocket火箭设计与仿真全攻略
  • MATLAB实战:手把手教你实现Gardner环路位同步(附完整代码)
  • EcomGPT-7B开源大模型部署案例:企业级电商AI工具链搭建全流程
  • FLUX.1-devAI应用:与Stable Diffusion ControlNet联动实现精准构图控制
  • 春联生成模型-中文-base应用:个人家庭、企业商家春节装饰方案
  • 颠覆性智能科学探索:AI-Scientist-v2引领自动化科研新纪元
  • OpenClaw自动化监控:GLM-4.7-Flash驱动的系统异常检测与报警
  • 2026新会陈皮优质品牌推荐榜:鹿茸品牌排行榜、鹿茸哪个牌子最好、鹿茸哪个牌子最正宗、鹿茸排名、鹿茸排行榜、鹿茸牌子排名选择指南 - 优质品牌商家
  • 别再直接升glibc 2.25了!CentOS7下从2.17平滑升级到2.31的保姆级排雷手册
  • TensorFlow-v2.15快速体验:无需担心依赖冲突,纯净环境随用随弃
  • Alist挂载云盘翻车实录:我在Termux里踩过的3个坑及完美解决方案
  • 黑金AX301开发板+HS-04模块:手把手教你用FPGA实现超声波测距(附完整Verilog代码)
  • 如何用MOOTDX实现Python量化分析:3个关键应用场景深度解析
  • 解决ModelScope与datasets版本兼容性问题的最佳实践
  • 2026四川茶歇服务优质品牌推荐榜安全定制双保障:订制茶歇、BBQ烧烤、公司茶歇定制、冷餐会公司、冷餐会宴会、冷餐会承接选择指南 - 优质品牌商家
  • WeChatExtension-ForMac突破微信功能壁垒:全方位提升macOS微信效率实战指南
  • Flutter打包APK/AAB保姆级教程:从签名文件生成到避坑指南
  • 百川2-13B-4bits量化版实测:OpenClaw连续执行8小时稳定性报告
  • 长沙旧房改造专业服务商排行及价格参考:长沙二手房翻新预算/长沙旧房厨卫改造/长沙旧房墙面改造/长沙旧房局部改造/选择指南 - 优质品牌商家
  • 高等数学零点定理实战:3个典型例题解析与常见误区避坑
  • 告别混乱数据:LAMMPS后处理中compute chunk/atom命令的深度解读与避坑指南
  • Redis未授权访问的隐藏风险:Momentum靶机渗透中的密码泄露案例分析
  • Emu3.5:vision、text 的vocab id 体系
  • OpenClaw浏览器自动化:Qwen3.5-9B驱动复杂网页操作实录
  • [实战] Windows环境下NTP时间同步的两种配置方案对比
  • 电路设计验证的开源解决方案:Fritzing核心功能技术解析
  • Cherry Studio vs Roo Code:手把手教你配置Qwen3-30B-A3B模型,接入IDA Pro MCP插件做逆向
  • Acode:重新定义Android移动代码编辑体验
  • OpenClaw技能市场巡礼:Top10个QwQ-32B增强技能推荐
  • AI诗人工作室:OpenClaw+nanobot生成藏头诗并自动排版成电子书