使用富文本编辑器时,我们一般期望可以自定义图片上传,在 Quill 中,粘贴图片时默认是将图片转为 base64文本的形式,存储在正文正,这显然不是我们想要的效果。
想要自定义 Quill 的图片粘贴上传,而不是转为 base64,需要自行覆盖编辑器的粘贴事件,然后自行实现图片上传与回显的逻辑,本文就以一个简单的示例来演示如何实现这个功能。
Quill是一款流行的开源富文本编辑器,官网地址:https://quilljs.com/
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
ts  quill.root.addEventListener("paste", (e) => {
    // 调用自定义的粘贴事件处理器
    overwriteParseImage(e, quill);
  });
tsconst 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 上传图片的基本步骤:
toolbar 选择图片功能;toolbar 选择图片功能ts  // 获取 quill 编辑器的toolbar【quill对象为上面提到的初始化的富文本编辑器】
  const toolbar = quill.getModule("toolbar");
  // 将图片功能指向自定义的选择图片事件
  // @ts-ignore
  toolbar.addHandler("image", selectLocalImage);
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);
  });
};
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;
}
这种方案虽然实现了图片居中,但靠右就不太好实现了,不知道你有没有什么好方法?欢迎评论解答!!!
建站因为热爱,生活需要Money,本站非常需要屏幕前的大佬动动您发财的小手,点击一次以示鼓励,祝您生活愉快!
PS:如果看不到广告,可能是网络原因或被拦截了。再次祝您生活愉快~~ 🥰
本文作者:DingDangDog
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!