You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Tauri中使用Quill.js时,如何在quill.clipboard.addMatcher中处理异步?

在Tauri中使用Quill.js处理粘贴图片的异步本地化方案

Quill的clipboard.addMatcher回调是同步执行的,无法直接返回异步操作结果,这里提供两种可行的解决方案:


方案一:占位符+文本变更事件异步替换

先插入临时占位符,待后端返回本地URL后再替换占位符:

// 存储临时URL与对应异步处理Promise的映射
const pendingImages = new Map();

quill.clipboard.addMatcher('img', (node, delta) => {
  // 生成唯一临时URL作为占位符
  const tempSrc = `temp://${Date.now()}-${Math.random().toString(36).slice(2)}`;
  // 缓存异步本地化任务
  pendingImages.set(tempSrc, localize(node.src));
  // 返回带占位符的Delta
  return new Delta().insert({ image: tempSrc });
});

// 监听文本变化,替换占位符为实际本地URL
quill.on('text-change', async () => {
  const contents = quill.getContents();
  let updateNeeded = false;

  for (const [index, op] of contents.ops.entries()) {
    const imgSrc = op.insert?.image;
    if (imgSrc?.startsWith('temp://')) {
      const promise = pendingImages.get(imgSrc);
      if (!promise) continue;

      updateNeeded = true;
      try {
        // 等待后端返回本地URL
        const localUrl = await promise;
        // 删除占位符并插入实际图片
        quill.deleteText(index, 1);
        quill.insertEmbed(index, 'image', localUrl);
      } catch (err) {
        console.error('图片本地化失败:', err);
        // 失败时回退到原URL或删除占位符
        quill.deleteText(index, 1);
        quill.insertEmbed(index, 'image', node.src);
      } finally {
        pendingImages.delete(imgSrc);
      }
    }
  }

  // 触发滚动更新确保内容渲染正确
  if (updateNeeded) {
    setTimeout(() => quill.scroll.update(), 0);
  }
});

async function localize(src) {
  if (src.startsWith('http')) {
    console.log(`${src} begins with http`);
    return invoke('localize', { src });
  }
  // 非HTTP链接直接返回原地址
  return src;
}

方案二:拦截粘贴事件直接处理HTML内容

直接接管粘贴流程,先批量处理图片URL再插入编辑器:

// 监听Quill编辑器根节点的粘贴事件
quill.root.addEventListener('paste', async (e) => {
  e.preventDefault(); // 阻止默认粘贴行为

  // 获取剪贴板中的HTML内容
  const htmlContent = e.clipboardData.getData('text/html');
  if (!htmlContent) return;

  // 创建临时DOM容器解析HTML
  const tempContainer = document.createElement('div');
  tempContainer.innerHTML = htmlContent;

  // 批量处理所有图片
  const imagePromises = Array.from(tempContainer.querySelectorAll('img')).map(async (img) => {
    if (img.src.startsWith('http')) {
      const localUrl = await invoke('localize', { src: img.src });
      img.src = localUrl;
    }
  });

  // 等待所有图片处理完成
  await Promise.all(imagePromises);

  // 将处理后的HTML插入Quill编辑器
  quill.clipboard.dangerouslyPasteHTML(tempContainer.innerHTML);
});

方案对比

  • 方案一:保留Quill默认的粘贴格式逻辑,仅替换图片URL,适合需要维持原有粘贴样式的场景。
  • 方案二:完全控制粘贴流程,可自由修改HTML结构,适合需要自定义粘贴内容的场景。

内容的提问来源于stack exchange,提问作者yoyoLooming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:50:25