基于Clipboard的复制粘贴实现

257 阅读3分钟

概述

复制粘贴是每一个编辑器都必备的基本功能。复制粘贴实现了把用户选择的某些数据复制下来,粘贴到用户指定的地方去。

通过复制粘贴功能,可以减少用户重复输入相同的内容, 大大提升用户的工作效率,改善用户的工作体验。

基本原理

知道了复制粘贴的重要性,那么在实际的开发中怎么实现产品的复制粘贴呢?它的基本原理如下:

image.png

在复制的时候,把源文档中的部分内容以一定的数据格式缓存到某个数据空间中;粘贴的时候,再取出缓存数据插入到目标文档中。

那么我们都可以通过哪些方式缓存数据呢?

  • 应用程序的内存空间。实现起来比较简单,但只能在应用内部进行复制粘贴。
  • 系统剪切板、浏览器剪切板(基于系统剪切板)。可以做到在计算机端内到处复制粘贴。
  • 服务端缓存。把数据缓存到服务端,支持跨端进行复制粘贴。

我们需要的复制粘贴

目前我们自己的产品主要跑在浏览器上,所以前期主要基于浏览器剪切板实现我们的复制粘贴功能。那剪切板应该具有什么样的能力呢?

  • 剪切板异步写入数据的能力。为什么需要呢?一方面复制内容过多时,同步写入会卡顿,影响用户体验;另一方面,复制时需要的部分数据需要异步获取。
  • 定制化MIME。为什么需要呢?每个产品的数据格式都是不一样的,剪切板提供的text、html等MIME是很难直接满足业务要求的。如果把数据转化成通用的格式,转换和反转换会有很大的性能损耗,更大的问题是会丢失部分原始信息。
  • 无网络环境下可以使用。产品支持离线可用。
  • http、https协议下都可以使用。支持用户自部署。

技术实现

在具体的技术落地实践上,我们当前采用的技术方案是拦截copy、cut、paste事件,自定义剪切板写入数据、读取数据,通过document.execCommand(‘copy‘)的方式写入数据。当然,使用这种方式存在一些明显的缺陷。

  • Document.execCommand()这个API处于Deprecated状态,web标准已不支持。

  • 虽然浏览器基本上都支持execCommand,但使用起来还是有很大的差别,需要开发者处理好浏览器兼容性问题。

    为什么不采用clipboard.js?clipboard.js是常用的一个操作剪切板的库,其基本原理也是使用了copy、cut、paste事件和execCommand API。使用起来,也有一些限制。

  • 不支持定制化MIME

  • 不支持同事写入多个MIME

    为什么不采用异步Clipboard API?异步Clipboard API是最新的web规范

  • 需要用户授权才可以使用

  • 安全上下文环境中可用,也就是只有在localhost、https环境下才可以使用

  • 浏览器的兼容性问题

  • 浏览器会对剪切板数据进行修正,在某些时候会丢失部分数据。之前遇到过一种场景是window环境下会丢失部分样式信息。

    通过浏览器插件的方式,实现复制粘贴也是很常用的一种方式,这需要用户主动装插件才可以。

后期扩展

目前的实现方案称不上多完美,每一种技术方案其实都有各自的优势和劣势,多种技术方案共用的话,需要处理好数据一致性的问题,这是后面要努力完善的一个方向。