uniapp富文本编辑器实战:从图片上传到内容导出全流程解析(附完整代码)
·
uniapp富文本编辑器实战:从图片上传到内容导出全流程解析(附完整代码)
在移动应用和Web开发中,富文本编辑功能已经成为内容型应用的标配需求。无论是博客系统、新闻发布后台还是社区论坛,都需要为用户提供强大的图文混排能力。uniapp作为跨平台开发框架,通过editor组件为开发者提供了统一的富文本编辑解决方案,本文将深入探讨其实战应用中的关键技术与完整实现流程。
1. 编辑器核心架构与初始化
uniapp的editor组件本质上是一个基于Webview的富文本编辑容器,它封装了不同平台的底层实现差异,为开发者提供一致的API接口。与传统的contenteditable方案相比,editor组件在非H5平台通过原生渲染实现,确保了跨平台的功能一致性。
典型初始化配置示例:
<editor
id="myEditor"
class="editor-container"
placeholder="开始创作..."
show-img-size
show-img-toolbar
@ready="onEditorReady"
@focus="onEditorFocus"
@statuschange="onStatusChange"
></editor>
关键属性说明:
show-img-size:启用图片尺寸显示show-img-toolbar:启用图片工具栏@ready:编辑器初始化完成事件
获取编辑器实例需要结合uni.createSelectorQuery():
onEditorReady() {
uni.createSelectorQuery()
.in(this)
.select('#myEditor')
.fields({
context: true
}, (res) => {
this.editorCtx = res.context
console.log('编辑器实例获取成功', this.editorCtx)
}).exec()
}
注意:编辑器实例的获取必须在组件mounted之后进行,建议在@ready事件中处理
2. 图片上传的完整实现方案
图片处理是富文本编辑中最复杂的环节之一,需要兼顾本地选取、上传过程和最终插入三个关键阶段。以下是经过实战验证的实现方案:
2.1 多平台兼容的图片选择
async chooseImages() {
const [err, res] = await uni.chooseImage({
count: 3,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera']
})
if (err) {
uni.showToast({ title: '选择图片失败', icon: 'none' })
return
}
this.uploadImages(res.tempFiles)
}
2.2 分步上传与进度反馈
async uploadImages(files) {
const uploadTasks = files.map(file => {
return new Promise((resolve, reject) => {
const uploadTask = uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: file.path,
name: 'file',
success: (res) => {
const data = JSON.parse(res.data)
resolve(data.url)
},
fail: reject
})
uploadTask.onProgressUpdate((res) => {
console.log(`上传进度: ${res.progress}%`)
})
})
})
try {
const imageUrls = await Promise.all(uploadTasks)
this.insertImages(imageUrls)
} catch (e) {
uni.showModal({ title: '上传失败', content: e.message })
}
}
2.3 智能插入与样式控制
insertImages(urls) {
urls.forEach(url => {
this.editorCtx.insertImage({
src: url,
width: '100%',
data: {
customAttr: 'image-' + Date.now()
},
success: () => {
console.log('图片插入成功')
}
})
})
}
图片处理最佳实践:
- 采用CDN地址而非本地路径
- 添加自定义data属性便于后续处理
- 统一宽度样式避免布局问题
- 实现上传失败的重试机制
3. 内容格式控制与交互优化
专业的富文本编辑器需要提供丰富的格式控制能力,同时保持流畅的用户体验。
3.1 文本样式控制API
// 加粗/取消加粗
toggleBold() {
this.editorCtx.format('bold', !this.isBold)
}
// 标题级别切换
setHeading(level) {
this.editorCtx.format('header', level ? `h${level}` : false)
}
// 文字颜色设置
setTextColor(color) {
this.editorCtx.format('color', color)
}
3.2 状态同步与UI反馈
通过@statuschange事件实现工具栏状态同步:
onStatusChange(e) {
const { detail } = e
this.formatState = {
bold: detail.hasOwnProperty('bold'),
italic: detail.hasOwnProperty('italic'),
header: detail.header || false
// 其他格式状态...
}
}
3.3 自定义分割线与特殊内容
// 插入分割线
insertDivider() {
this.editorCtx.insertDivider({
success: () => console.log('分割线插入成功')
})
}
// 插入自定义HTML
insertHTML(html) {
this.editorCtx.insertHTML(html)
}
4. 内容导出与安全处理
内容导出是富文本编辑的最后关键环节,需要处理多种格式和安全性问题。
4.1 多格式导出实现
exportContent() {
this.editorCtx.getContents({
success: (res) => {
console.log('HTML内容:', res.html)
console.log('纯文本内容:', res.text)
console.log('Delta格式:', res.delta)
// 处理导出内容
this.processContent(res.html)
}
})
}
4.2 XSS防护与内容过滤
import xss from 'xss' // 使用xss库
processContent(html) {
const options = {
whiteList: {
a: ['href', 'title', 'target'],
img: ['src', 'alt', 'width'],
p: [],
span: ['style']
// 其他允许的标签和属性...
},
css: {
whiteList: {
color: true,
'background-color': true
}
}
}
this.cleanHtml = xss(html, options)
}
4.3 与服务端的交互方案
async submitContent() {
const { html, text } = await this.getEditorContent()
const res = await uni.request({
url: '/api/content',
method: 'POST',
data: {
html,
text,
summary: text.substring(0, 140)
}
})
if (res.success) {
uni.showToast({ title: '发布成功' })
}
}
5. 性能优化与异常处理
在实际项目中,富文本编辑器可能面临性能瓶颈和各类异常情况。
5.1 大内容加载策略
// 分块加载内容
loadLargeContent(content) {
const chunkSize = 50000
let offset = 0
const loadNextChunk = () => {
const chunk = content.substring(offset, offset + chunkSize)
this.editorCtx.insertHTML(chunk, () => {
offset += chunkSize
if (offset < content.length) {
setTimeout(loadNextChunk, 100)
}
})
}
loadNextChunk()
}
5.2 内存管理与防崩溃
// 定期清理历史记录
setInterval(() => {
this.editorCtx.clearHistory()
}, 300000)
// 错误边界处理
window.onerror = (message) => {
if (message.includes('editor')) {
console.error('编辑器异常:', message)
uni.showModal({
title: '编辑器异常',
content: '建议保存当前内容后刷新页面'
})
}
}
5.3 平台差异处理方案
// 条件编译处理平台差异
// #ifdef MP-WEIXIN
this.editorConfig.maxImageSize = 1048576 // 微信小程序限制
// #endif
// #ifdef H5
this.editorConfig.maxImageSize = 5242880 // H5限制更大
// #endif
在真实项目开发中,我们发现编辑器性能与内容体积呈指数关系变化。当内容超过2万字时,建议采用分段加载策略。对于图片密集型内容,提前压缩和CDN加速是必要的优化手段。
更多推荐


所有评论(0)