如何在JavaScript中复制到剪贴板?

38 浏览
0 Comments

如何在JavaScript中复制到剪贴板?

如何将文本复制到剪贴板(多浏览器)?

相关: Trello 如何访问用户的剪贴板?

admin 更改状态以发布 2023年5月20日
0
0 Comments

自动复制到剪贴板可能会有危险,因此大多数浏览器(除了Internet Explorer)都会使它非常困难。个人来说,我使用以下简单的技巧:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

用户将看到提示框,要复制的文本已经被选中。现在只需要按下Ctrl+CEnter(关闭框)- 就行了!

现在剪贴板复制操作是安全的,因为用户是手动进行的(但非常简单明了)。当然,它适用于所有浏览器。


0
0 Comments

总览

有三个主要的浏览器API可以用于复制到剪贴板:

  1. 异步剪贴板API [navigator.clipboard.writeText]

    • 在Chrome 66(2018年3月)中提供了针对文本的部分。
    • 访问是异步的,并使用JavaScript Promises,可以编写使安全用户提示(如果显示)不会中断页面中的JavaScript的代码。
    • 文本可以直接从变量复制到剪贴板。
    • 仅支持通过HTTPS提供的页面。
    • 在Chrome 66中,处于非活动标签页的页面可以在不需要权限提示的情况下写入剪贴板。
  2. document.execCommand('copy')(已弃用)

    • 大多数浏览器从2015年4月左右开始支持此功能(请参见以下的浏览器支持)。
    • 访问是同步的,即在完成拷贝操作之前包括显示和用户与任何安全提示的交互,JavaScript代码会停止在页面中。
    • 文本从DOM中读取并放置到剪贴板中。
    • 在2015年4月的测试中,只有Internet Explorer显示了在写入剪贴板时显示权限提示的情况。
  3. 覆盖复制事件

    • 请参见剪贴板API文档中有关覆盖复制事件的内容。
    • 允许您修改从任何复制事件出现在剪贴板上的内容,可以包括其他格式的数据,而不仅仅是纯文本。
    • 这里没有详细介绍,因为它不能直接回答问题。

一般开发注意事项

不要期望在控制台测试代码时剪贴板相关的命令可以正常工作。一般而言,该页面必须处于活动状态(异步剪贴板API)或需要用户交互(例如用户点击)才能访问剪贴板(document.execCommand('copy'))) 有关更多详细信息,请参见下文。

重要提示(2020年2月20日更新)

请注意,自从本文最初发布以来,跨源IFrame权限的停用和其他IFrame“沙盒化”导致嵌入的演示“运行代码片段”按钮和“codepen.io示例”无法在一些浏览器(包括Chrome和Microsoft Edge)中运行。

为了开发创建您自己的网页,请通过HTTPS连接提供该页面以进行测试和开发。

这里有一个测试/演示页面,展示了代码的运行:
https://deanmarktaylor.github.io/clipboard-test/

异步+后备

由于新的异步剪贴板API的浏览器支持程度不同,您可能需要退而使用document.execCommand('copy')方法来获得良好的浏览器覆盖率。

这是一个简单的示例(可能无法在此网站中嵌入,请阅读上面的“重要提示”):

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();
  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }
  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});


  
  
  

(codepen.io示例可能无法工作,请阅读上面的“重要提示”)
请注意,这个片段在Stack Overflow的嵌入式预览中运行得不太好,您可以在这里尝试:https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

异步剪贴板API

请注意,Chrome 66中有一种“请求权限”并通过权限API测试访问剪贴板的能力。

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand('copy')

这篇文章的其余部分详细介绍了document.execCommand('copy')API的细微差别和详细信息。

浏览器支持

JavaScriptdocument.execCommand('copy')支持已经增加了,有关浏览器更新的链接如下:已被废弃

简单示例

(在此网站中嵌入可能无法正常工作,请阅读上面的“注意”)

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');
copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();
  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});


复杂示例:将文本复制到剪贴板而不显示输入框

上面的简单示例适用于屏幕上有textareainput元素的情况。

在某些情况下,您可能希望在不显示input / textarea元素的情况下将文本复制到剪贴板。这是一个解决这个问题的例子(基本上是插入一个元素,复制到剪贴板,删除元素):

已在 Google Chrome 44、Firefox 42.0a1 和 Internet Explorer 11.0.8600.17814 上测试。

(可能无法在此网站中嵌入使用,请参阅上文的“重要”说明)

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if the element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a
  // flash, so some of these are just precautions. However in
  // Internet Explorer the element is visible whilst the popup
  // box asking the user for permission for the web page to
  // copy to the clipboard.
  //
  // Place in the top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;
  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';
  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;
  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';
  // Avoid flash of the white box if rendered for any reason.
  textArea.style.background = 'transparent';
  textArea.value = text;
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();
  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
  document.body.removeChild(textArea);
}
var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');
copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});
copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});


  
  
  

其他注意事项

仅在用户执行操作时起作用

所有 document.execCommand('copy') 调用必须作为用户操作的直接结果,例如 click 事件处理程序。这是为了防止在用户不期望的情况下破坏其剪贴板。

有关更多信息,请参见此处的 Google 开发人员文章

剪贴板 API

请注意,完整的剪贴板 API 草案规范可在此处找到:
https://w3c.github.io/clipboard-apis/

是否被支持?

  • document.queryCommandSupported('copy') 如果“浏览器支持该命令”,则应返回 true
  • document.queryCommandEnabled('copy') 如果现在调用 document.execCommand('copy') 将成功,则也返回 true。检查以确保命令是从用户发起的线程中调用,并满足其他要求。

然而,作为浏览器兼容性问题的一个示例,从大约 2015 年 4 月到 10 月,Google Chrome 仅在从用户发起的线程中调用命令时才从 document.queryCommandSupported('copy') 中返回 true

请注意下方的兼容性细节。

浏览器兼容性详解

虽然简单地调用document.execCommand('copy'),并将其包装在try/catch块中,作为用户单击的结果,可以获得最兼容性的使用,但以下的情况有一些注意点:

任何对document.execCommanddocument.queryCommandSupporteddocument.queryCommandEnabled的调用都应该被包装在try/catch块中。

不同的浏览器实现和浏览器版本在调用时会抛出不同类型的异常,而不是返回false

不同的浏览器实现仍处于不断变化之中,Clipboard API仍然处于起草阶段,因此请记得进行测试。

0