乐闻世界logo
搜索文章和话题

JS 如何将内容复制到剪贴板

7 个月前提问
3 个月前修改
浏览次数71

6个答案

1
2
3
4
5
6

在JavaScript中,要将文本复制到剪贴板,你可以使用navigator.clipboard.writeText()方法。这是一个简单的现代浏览器API,用于向剪贴板写入文本。

以下是使用这个API的例子:

javascript
// 要复制的文本 const textToCopy = "要复制的文本内容"; // 使用Clipboard API复制文本到剪贴板 navigator.clipboard.writeText(textToCopy).then(() => { console.log("文本已经成功复制到剪贴板!"); }).catch(err => { console.error("无法复制文本: ", err); });

请注意,由于安全原因,现代浏览器通常要求writeText方法在由用户行为(如点击事件)触发的函数中调用。如果你尝试在非用户触发的事件中调用它(例如,在页面加载时),浏览器可能会阻止该操作。

此外,某些浏览器可能还需要页面通过HTTPS服务,而不是HTTP,才允许使用Clipboard API。

这是一个HTML按钮和JavaScript代码结合使用navigator.clipboard.writeText()方法的示例:

html
<button id="copyButton">复制文本</button>
javascript
document.getElementById('copyButton').addEventListener('click', function() { const textToCopy = "要复制的文本内容"; navigator.clipboard.writeText(textToCopy).then(() => { console.log("文本已经成功复制到剪贴板!"); }).catch(err => { console.error("无法复制文本: ", err); }); });

在这个例子中,当用户点击按钮时,textToCopy中的文本会被复制到剪贴板。

2024年6月29日 12:07 回复

概述

复制到剪贴板的浏览器 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/02/20 在此注明)

请注意,由于本文最初是在跨源 IFRAME和其他IFRAME“沙盒”中弃用权限,因此会阻止嵌入式演示“运行代码片段”按钮和“codepen.io 示例”在某些浏览器(包括 Chrome 和 Microsoft Edge)中工作)。

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

这是一个测试/演示页面,演示了代码的工作原理: https ://deanmarktaylor.github.io/clipboard-test/

异步+回退

由于浏览器对新的异步剪贴板 API 的支持级别,您可能希望回退到该document.execCommand('copy')方法以获得良好的浏览器覆盖率。

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

shell
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'); }); <div style="display:inline-block; vertical-align:top;"> <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br /> <button class="js-copy-jane-btn">Set clipboard to JANE</button> </div> <div style="display:inline-block;"> <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard: </textarea> </div>

运行代码片段Hide results

展开片段

(codepen.io 示例可能不起作用,请阅读上面的“重要”注释)请注意,此代码片段在 Stack Overflow 的嵌入式预览中运行不佳,您可以在这里尝试:https ://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors =1011

异步剪贴板 API

请注意,Chrome 66 中可以通过权限 API“请求权限”并测试对剪贴板的访问。

shell
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('复制')

本文的其余部分将讨论document.execCommand('copy')API 的细微差别和细节。

浏览器支持

JavaScriptdocument.execCommand('copy')支持已增加,请参阅以下链接了解浏览器更新: (已弃用)👎

简单的例子

(可能无法嵌入本网站,请阅读上面的“重要”注释)

shell
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'); } }); <p> <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button> <textarea class="js-copytextarea">Hello I'm some text</textarea> </p>

运行代码片段Hide results

展开片段

复杂示例:复制到剪贴板而不显示输入

如果屏幕上有可见的textarea或元素,上面的简单示例效果很好。input

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

使用 Google Chrome 44、Firefox 42.0a1 和 Internet Explorer 11.0.8600.17814 进行测试。

(可能无法嵌入本网站,请阅读上面的“重要”注释)

shell
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'); }); <div style="display:inline-block; vertical-align:top;"> <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br /> <button class="js-copy-jane-btn">Set clipboard to JANE</button> </div> <div style="display:inline-block;"> <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard: </textarea> </div>

运行代码片段Hide results

展开片段

补充笔记

仅当用户采取操作时才有效

所有document.execCommand('copy')调用都必须作为用户操作的直接结果发生,例如单击事件处理程序。这是一种防止用户剪贴板在意外情况下被弄乱的措施。

请参阅此处的 Google 开发者帖子了解更多信息。

剪贴板API

请注意,完整的 Clipboard API 草案规范可以在这里找到: https://w3c.github.io/clipboard-apis/

支持吗?

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

但是,作为浏览器兼容性问题的一个示例,2015 年 4 月到 10 月期间的 Google Chrome 仅truedocument.queryCommandSupported('copy')从用户启动的线程调用该命令时返回。

请注意下面的兼容性详细信息。

浏览器兼容性详细信息

document.execCommand('copy')虽然对包装在try/块中的简单调用catch(由于用户单击而调用)将为您提供最大的兼容性,但使用以下内容有一些附带条件:

document.execCommand, document.queryCommandSupportedor 的任何调用都document.queryCommandEnabled应该包含在try/catch块中。

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

不同的浏览器实现仍在不断变化,剪贴板 API仍处于草案阶段,因此请记住进行测试。

2024年6月29日 12:07 回复

自动复制到剪贴板可能很危险,因此大多数浏览器(Internet Explorer 除外)都使其变得非常困难。就我个人而言,我使用以下简单的技巧:

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

用户将看到提示框,其中已选择要复制的文本。现在按Ctrl+C和Enter(关闭框)就足够了——瞧!

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

shell
<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button> <script> function copyToClipboard(text) { window.prompt("Copy to clipboard: Ctrl+C, Enter", text); } </script>

运行代码片段Hide results

展开片段

2024年6月29日 12:07 回复

以下方法适用于 Chrome、Firefox、Internet Explorer 和 Edge 以及最新版本的 Safari(2016 年 10 月发布的版本 10 中添加了复制支持)。

  • 创建一个文本区域并将其内容设置为要复制到剪贴板的文本。
  • 将文本区域附加到 DOM。
  • 选择文本区域中的文本。
  • 调用 document.execCommand("copy")
  • 从 dom 中删除 textarea。

注意:您将看不到文本区域,因为它是在 Javascript 代码的同一同步调用中添加和删除的。

如果您自己实施此操作,需要注意一些事项:

  • 出于安全原因,这只能从事件处理程序(例如单击)中调用(就像打开窗口一样)。
  • 首次更新剪贴板时,Internet Explorer 将显示权限对话框。
  • 当文本区域聚焦时,Internet Explorer 和 Edge 将滚动。
  • execCommand() 在某些情况下可能会抛出异常。
  • 除非您使用文本区域,否则换行符和制表符可能会被吞掉。 (大多数文章似乎都推荐使用div)
  • 当显示 Internet Explorer 对话框时,文本区域将可见,您需要隐藏它,或者使用 Internet Explorer 特定的剪贴板数据 API。
  • 在 Internet Explorer 中,系统管理员可以禁用剪贴板 API。

下面的函数应该尽可能干净地处理以下所有问题。如果您发现任何问题或有任何改进建议,请发表评论。

shell
// Copies a string to the clipboard. Must be called from within an // event handler such as click. May return false if it failed, but // this is not always possible. Browser support for Chrome 43+, // Firefox 42+, Safari 10+, Edge and Internet Explorer 10+. // Internet Explorer: The clipboard feature may be disabled by // an administrator. By default a prompt is shown the first // time the clipboard is used (per session). function copyToClipboard(text) { if (window.clipboardData && window.clipboardData.setData) { // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible. return window.clipboardData.setData("Text", text); } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) { var textarea = document.createElement("textarea"); textarea.textContent = text; textarea.style.position = "fixed"; // Prevent scrolling to bottom of page in Microsoft Edge. document.body.appendChild(textarea); textarea.select(); try { return document.execCommand("copy"); // Security exception may be thrown by some browsers. } catch (ex) { console.warn("Copy to clipboard failed.", ex); return prompt("Copy to clipboard: Ctrl+C, Enter", text); } finally { document.body.removeChild(textarea); } } }

https://jsfiddle.net/fx6a6n6x/

2024年6月29日 12:07 回复

这是我对此的看法......

shell
function copy(text) { var input = document.createElement('input'); input.setAttribute('value', text); document.body.appendChild(input); input.select(); var result = document.execCommand('copy'); document.body.removeChild(input); return result; }

@korayem:请注意,使用 htmlinput字段不会考虑换行符\n,并且会将任何文本展平为单行。

正如 @nikksan 在评论中提到的,使用textarea将解决问题如下:

shell
function copy(text) { var input = document.createElement('textarea'); input.innerHTML = text; document.body.appendChild(input); input.select(); var result = document.execCommand('copy'); document.body.removeChild(input); return result; }
2024年6月29日 12:07 回复

从网页读取和修改剪贴板会引起安全和隐私问题。但是,在 Internet Explorer 中,可以做到这一点。我找到了这个示例片段

shell
<script type="text/javascript"> function select_all(obj) { var text_val=eval(obj); text_val.focus(); text_val.select(); r = text_val.createTextRange(); if (!r.execCommand) return; // feature detection r.execCommand('copy'); } </script> <input value="http://www.sajithmr.com" onclick="select_all(this)" name="url" type="text" />

运行代码片段Hide results

展开片段

2024年6月29日 12:07 回复

你的答案