2024-11-05
温故知新
00

目录

简介
粘贴图片上传
1.拦截粘贴图片事件
2.监听编辑器粘贴事件
3.自定义粘贴事件处理器
覆盖上传图片按钮事件
1.覆盖 toolbar 选择图片功能
2.自行时间隐藏式的选择图片功能
3.自定义上传图片功能
总结及问题

简介

使用富文本编辑器时,我们一般期望可以自定义图片上传,在 Quill 中,粘贴图片时默认是将图片转为 base64文本的形式,存储在正文正,这显然不是我们想要的效果。

想要自定义 Quill 的图片粘贴上传,而不是转为 base64,需要自行覆盖编辑器的粘贴事件,然后自行实现图片上传与回显的逻辑,本文就以一个简单的示例来演示如何实现这个功能。

Quill是一款流行的开源富文本编辑器,官网地址:https://quilljs.com/

粘贴图片上传

1.拦截粘贴图片事件

ts
// 初始化富文本编辑框【提示:vue3的setup语法糖写法,请在onMounted中初始化quill编辑器】 const quill = new Quill("#editor", options); // img粘贴事件拦截 quill.clipboard.addMatcher("img", (node, delta) => { return delta; // 阻止 Quill 默认的图片插入行为(这里没有阻止,是为了防止图片上传失败时,仍然保持base64图片可见) });

PS: quill.clipboard.addMatcher("img") 在最新版Quill中(2.0.2),不起作用,因此拦截实际没有生效。详见:https://github.com/slab/quill/issues/4337

2.监听编辑器粘贴事件

ts
quill.root.addEventListener("paste", (e) => { // 调用自定义的粘贴事件处理器 overwriteParseImage(e, quill); });

3.自定义粘贴事件处理器

ts
const overwriteParseImage = (e: ClipboardEvent, q: Quill) => { // 判断如果粘贴内容不为空,并且粘贴的是特殊元素或文件,则执行自定义逻辑 if (e.clipboardData && (e.clipboardData.items || e.clipboardData.files)) { const items = e.clipboardData.items || e.clipboardData.files; // 图片格式正则,自行修改!!! const IMAGE_MIME_REGEX = /^image\/(jpe?g|gif|png|svg|webp)$/i; // 阻止默认行为 e.stopPropagation(); e.preventDefault(); // 遍历上传图片(图片可能是多张) for (let i = 0; i < items.length; i++) { if (IMAGE_MIME_REGEX.test(items[i].type)) { const file = items[i].getAsFile() ? items[i].getAsFile() : items[i]; if (file) { const formData = new FormData(); // @ts-ignore formData.append("file", file); // uploadPublicFile 为自定义图片上传方法,不做展示,根据自己业务实现即可 uploadPublicFile(formData).then((res) => { const range = q.getSelection(); // 获取当前光标位置 if (range && res.c == 200) { // 图片上传成功后,删除原base64图片,替换为上传成功后的图片url【这部分逻辑请根据自己业务实现】 q.deleteText(range.index - 2, 2, "user"); // 删除图片占位符 q.insertEmbed(range.index, "image", res.d?.fileUrl); // 插入上传后的图片 URL } }); } } } } };

覆盖上传图片按钮事件

除了粘贴事件自定义上传图片外,Quill 编辑器也有自己的上传图片 toolbar,为何更好的使用体验,我们还要在 toolbar 选择图片时改为上传图片。

要想实现 toolbar 选择图片时改为上传图片,与粘贴图片该为上传图片的逻辑是类似的,只不过代码写法有所不同,自定义 toolbar 上传图片的基本步骤:

  1. 覆盖 toolbar 选择图片功能;
  2. 自行实现选择图片功能;
  3. 自行实现图片上传与回显逻辑。

1.覆盖 toolbar 选择图片功能

ts
// 获取 quill 编辑器的toolbar【quill对象为上面提到的初始化的富文本编辑器】 const toolbar = quill.getModule("toolbar"); // 将图片功能指向自定义的选择图片事件 // @ts-ignore toolbar.addHandler("image", selectLocalImage);

2.自行时间隐藏式的选择图片功能

ts
// 图片选择器【一个隐藏的html-input元素】 const quillImageSelect = ref(); const selectLocalImage = () => { // 初始化图片选择输入框 quillImageSelect.value = document.createElement("input"); quillImageSelect.value.setAttribute("type", "file"); quillImageSelect.value.setAttribute("accept", "image/*"); quillImageSelect.value.setAttribute("style", "visibility:hidden"); // 设置为隐藏 // 自定义的图片上传功能绑定onchange事件【quillImageUpload为自定义功能函数】 quillImageSelect.value.onchange = quillImageUpload.bind( quillImageSelect.value ); document.body.appendChild(quillImageSelect.value); quillImageSelect.value.click(); // 模拟点击事件,自动开始图片选择上传 window.requestAnimationFrame(() => { document.body.removeChild(quillImageSelect.value); }); };

3.自定义上传图片功能

ts
// 函数包装一层,便于绑定 const quillImageUpload = () => { imageUpload(quill); }; // 真正的图片上传功能函数【一次只能选择一张图片】 const imageUpload = (q: Quill) => { const file = quillImageSelect.value.files[0]; const fileReader = new FileReader(); if (file) { fileReader.readAsDataURL(file); } const formData = new FormData(); formData.append("file", file); // uploadPublicFile 为自定义图片上传功能代码,请根据自身业务实现即可 uploadPublicFile(formData).then((res) => { // console.log(res); const range = q.getSelection(); // 获取当前光标位置 if (range && res.c == 200) { // 删除base64图片,与粘贴事件处理一致,请基于自己业务自行修改 q.deleteText(range.index, 1); // 删除图片占位符 q.insertEmbed(range.index, "image", res.d?.fileUrl); // 插入上传后的图片 URL } }); };

总结及问题

Quill无疑是一款好用的开源服务本编辑器,但对于自定义图片上传还是不太适配,很多需要自行实现的逻辑,不知道后面会不会优化这个功能?

PS:有一个问题,Quill编辑器采用的居中实现方案是class="text-center",即text-align:center; ,这种方案可能适用于 base64 格式的图片,但由于我们自定义图片上传后,图片实际显示的是 img 标签,所以这种居中方案不再适用于图片,因此我们需要自行覆盖一下这个居中实现方案,目前我采用的是 margin 方案,即:

css
.text-center img { margin: 0 auto; }

这种方案虽然实现了图片居中,但靠右就不太好实现了,不知道你有没有什么好方法?欢迎评论解答!!!

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:DingDangDog

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!