纯 JavaScript 实现将内容复制到剪切板

最后更新:
阅读次数:

据说以前要是需要 将内容复制到剪切板 这个功能时,得用到 flash。

但是现在时代不同了,前端出现了一堆新的功能更加强大的 API(正式发布的、还在审核中的等)。

现在我有 3 种方法来实现这个功能。

方案一

实现思路

  1. 首先在页面上插入一个隐藏的 input 元素
  2. 将需要复制的数据用 js 写入到 input 元素的 value
  3. 执行 input 元素的 select() 方法,选中要被复制的文本
  4. 执行 document.execCommand('copy') 进行复制

源代码

<input id="temp-copy-area" type="text" />
// 下面注意不要为元素设置为 display: none 或 width: 0,元素必须有一定的宽度高度
#temp-copy-area {
display: block;
position: absolute;
z-index: -1;
width: 1px;
height: 1px;
opacity: 0;
}
function copy() {
let tempCopyArea = document.getElementById("temp-copy-area");

// 将 value 设为自己想要复制的值
tempCopyArea.value = "将被复制的值1";

tempCopyArea.select();

// 执行复制命令
if (document.queryCommandSupported("copy")) {
document.execCommand("copy");
}
}

方案二

实现思路

  1. 首先在页面上插入一个隐藏的 div 元素
  2. 将需要复制的数据用 js innerText 写入到 div 中
  3. 新建一个 Range 对象,并让其包含上面的 div 节点
  4. 新建一个 Selection 对象,并将上面的 Range 对象添加到选取对象
  5. 执行 document.execCommand('copy') 进行复制

源代码

<div id="temp-copy-area"></div>
#temp-copy-area {
position: absolute;
z-index: -1;
width: 1px;
height: 1px;
opacity: 0;
}
// 一个 Range 对象表示了包含节点和部分文本节点的文档片段

function copy() {
let tempCopyArea = document.getElementById("temp-copy-area");

tempCopyArea.innerText = "将被复制的值2";

// 新建一个 Range 对象
let range = document.createRange();

// 设置 Range 对象以包含指定的节点
range.selectNode(tempCopyArea);

// 新建一个选区对象 Selection
let selection = window.getSelection();

// 去除选区对象中默认的选区内容
if (selection.rangeCount > 0) {
selection.removeAllRanges();
}

// 将 Range 对象加入到当前选区对象
selection.addRange(range);

// 执行复制命令
if (document.queryCommandSupported("copy")) {
document.execCommand("copy");
}
}

方案三

实现思路

选中文本,Ctrl+C 或执行 document.execCommand('copy') 都会触发 copy 事件。

  1. 监听 copy 事件,更改 copy 事件的默认行为
  2. 已合适的方式出发 copy 事件

源代码

// 监听 copy 事件
document.addEventListener("copy", function(e) {
e.clipboardData.setData("text/plain", "将被复制的值3");

// 禁用 copy 事件的默认行为:复制选中的文本
e.preventDefault();
});

// 触发 copy 事件
function copy() {
if (document.queryCommandSupported("copy")) {
document.execCommand("copy");
}
}

总结

  • 第一种和第二种方法适用于大多数浏览器。

    • 但是请注意:在为第一种和第二种方法的存放复制的数据节点设置了 CSS user-select: none 后,会不起作用。
  • 第三种方法用到了 Clipboard API,兼容性还不太好

  • IOS 有坑,三种方法谨慎使用。(因为我之前做测试时,document.queryCommandSupported('copy') 居然返回了 false