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

Posted

技术标签:

【中文标题】如何在 JavaScript 中复制到剪贴板?【英文标题】:How do I copy to the clipboard in JavaScript? 【发布时间】:2010-09-28 20:24:49 【问题描述】:

将文本复制到剪贴板(多浏览器)的最佳方式是什么?

我试过了:

function copyToClipboard(text) 
    if (window.clipboardData)  // Internet Explorer
        window.clipboardData.setData("Text", text);
     else 
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
        clipboardHelper.copyString(text);
    

但在 Internet Explorer 中,它会出现语法错误。在 Firefox 中,它说 unsafeWindow is not defined

不使用Flash 的好技巧:How does Trello access the user's clipboard?

【问题讨论】:

只是好奇,你想复制到剪贴板而用户不能自己做的事情是什么? 没什么特别的。他们可以自己做,但我还想提供点击按钮的可能性,而不必担心选择正确的文本部分。 这篇长篇博文包含很多方法:Accessing the System Clipboard with javascript – A Holy Grail? 它在 IE 和 FF 中给浏览器未定义的异常 如果我们可以将文本放入用户的剪贴板,我们就可以毁掉他的剪贴板。 【参考方案1】:

概述

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

    Async Clipboard API[navigator.clipboard.writeText]

    Chrome 66 (March 2018) 中提供以文本为中心的部分 访问是异步的并使用JavaScript Promises,可以这样编写,以便安全用户提示(如果显示)不会中断页面​​中的 JavaScript。 文本可以直接从变量复制到剪贴板。 仅在通过 HTTPS 提供的页面上受支持。 在 Chrome 66 页面中,非活动标签可以在没有权限提示的情况下写入剪贴板。

    document.execCommand('copy') (deprecated) ?

    截至 2015 年 4 月,大多数浏览器都支持此功能(请参阅下面的浏览器支持)。 访问是同步的,即停止页面中的 JavaScript 直到完成,包括显示和用户与任何安全提示进行交互。 从 DOM 中读取文本并将其放置在剪贴板上。 在测试期间 ~ 2015 年 4 月,只有 Internet Explorer 被记录为在写入剪贴板时显示权限提示。

    覆盖复制事件

    请参阅 Overriding the copy event 上的剪贴板 API 文档。 允许您修改任何复制事件中显示在剪贴板上的内容,可以包括纯文本以外的其他格式的数据。 此处未涉及,因为它不能直接回答问题。

一般开发说明

当您在控制台中测试代码时,不要期望剪贴板相关的命令能够正常工作。通常,页面需要处于活动状态(异步剪贴板 API)或需要用户交互(例如用户单击)以允许 (document.execCommand('copy')) 访问剪贴板,详情请参见下文。

重要提示(此处注明 2020/02/20)

请注意,由于这篇文章最初是由deprecation of permissions in cross-origin IFRAMEs 和其他IFRAME "sandboxing" 编写的,因此会阻止嵌入式演示“运行代码 sn-p”按钮和“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');
);
<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>

(codepen.io 示例可能不起作用,请阅读上面的“重要”说明) 请注意,此 sn-p 在 Stack Overflow 的嵌入式预览中效果不佳,您可以在此处尝试:https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

异步剪贴板 API

MDN Reference Chrome 66 announcement post (March 2018) 参考Async Clipboard 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 的细微差别和细节。

浏览器支持

JavaScript document.execCommand('copy') 支持已增加,请参阅以下链接了解浏览器更新: (deprecated) ?

Internet Explorer 10+(尽管this document 表示 Internet Explorer 5.5+ 提供了一些支持)。 Google Chrome 43+ (~April 2015) Mozilla Firefox 41+ (shipping ~September 2015) Opera 29+ (based on Chromium 42, ~April 2015)

简单示例

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

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>

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

如果屏幕上可以看到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');
);
<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>

补充说明

仅当用户采取行动时才有效

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

请参阅Google Developers post here 了解更多信息。

剪贴板 API

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

是否支持?

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

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

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

浏览器兼容性详情

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

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

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

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

【讨论】:

抱歉打扰了,但是document.execCommand is obsolete。见developer.mozilla.org/en-US/docs/Web/API/Document/execCommand @tnkh 当然,但替代品(剪贴板 API)尚未完全烘焙和支持。 目前全球 91% 的用户都支持剪贴板 API:caniuse.com/mdn-api_clipboard_writetext 样式注意事项:我只使用opacity: 0 来隐藏&lt;textarea&gt;。还有z-index:-1,如果你想完全安全的话。所以我们实际上只需要定义三个样式属性:position: fixed 和前面提到的两个。 我只是在回退后添加了焦点的重置:var previousFocusElement = document.activeElement (....all the fallback code...) previousFocusElement.focus();【参考方案2】:

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

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

向用户显示提示框,其中已选择要复制的文本。现在按下 Ctrl + CEnter (关闭框)就足够了——瞧!

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

<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>

【讨论】:

但是该对话框中显示的字符数量有限制,因此要复制的数据量也有限制。 聪明,但这只支持单行。 将“提示”功能更改为自定义模式很简单,关键在于使用可编辑的内容字段并预先选择文本,并且不会破坏浏览器UI 通过强制用户自己执行操作。一个++ 如果您的文本超过 2000 个字符,它将被截断,但对于较小的文本样本,它效果很好 @RasTheDestroyer - 在 2k 字符处截断似乎是 Chrome 的问题,但无论如何都很高兴知道【参考方案3】:

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

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

注意:您不会看到 textarea,因为它是在 Javascript 代码的同一个同步调用中添加和删除的。

如果您自己实现此功能需要注意一些事项:

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

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

// 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/

【讨论】:

不错的答案:跨浏览器支持,错误处理 + 清理。从今天对 queryCommandSupported 的新支持开始,复制到剪贴板现在在 Javascript 中是可行的,这应该是公认的答案,而不是笨拙的 'window.prompt("Copy to clipboard: Ctrl+C, Enter", text)' 解决方法。 IE9支持window.clipboardData,所以你应该在浏览器支持列表中添加IE9,我认为IE8及之前的版本也可能,但需要验证。 @SantiagoCorredoira:在 2016 年,这应该是公认的答案。请考虑重新分配 BGT(绿色大勾号)。 @Noitidart 我测试过,它适用于 firefox 54、chrome 60 和 edge 浏览器,即使焦点不在 html 文档中,您遇到的错误也可能特定于版本 FF 55 @Noitidart 它在这里仍然可以完美运行,专注于开发工具并没有阻止它。顺便说一句,普通的网络应用用户会在开发者工具上做什么 jQuery UI 用户:请注意,如果您尝试在模式对话框中使用此功能,则会遇到此方法的问题。我怀疑这是因为 jQuery UI 模式正在管理/操作文档焦点。如果它适合您的用例,一种解决方法是先关闭模式对话框,然后复制文本。或者,简单地使用非模态对话框。我怀疑您也可以修改此函数,以便将文本区域添加到模态而不是正文。【参考方案4】:

这是我对那个的看法......

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:请注意,使用 html input 字段不会尊重换行符 \n 并将任何文本拼合为一行。

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

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;

【讨论】:

@sof-03 使用 textarea 代替 input 并添加 \r\n 换行 在 Win10x64 上的 Microsoft Edge 42.17134.1.0 中不工作 我已经复制了你的答案。它适用于 chrome,这就是我所需要的。 这是最简单的解决方案,适用于 Firefox v68.0.2(64 位)。 出于某种原因,我通常的“创建一个隐藏的输入或文本区域,然后选择它并执行命令”不起作用,这是迄今为止列出的最佳解决方案,尽管其他解决方案很全面并且喜欢完整的***页面,这个对我来说效果很好,所以 +1【参考方案5】:

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

    <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" />

【讨论】:

使用 flash 进行简单的复制操作似乎有点矫枉过正,很高兴有一种干净的 JS 方法可以做到这一点。而且由于我们处于企业环境中。 IE很好。谢谢班迪! 请解释 execCommand(\\’copy\\’); 的作用,如果不复制到 IE 的剪贴板? @mrBorna 不要使用if(!document.all)if(!r.execCommand) 以免其他人实现它! Document.all 与此完全无关。 当人们使用 Flash 更改剪贴板时,为什么这些隐私问题十年来从未提出过?如果我们只允许一种方式(即复制,而不是阅读其内容),这会如何产生隐私问题? @MuhammadbinYusrat:虽然不是隐私问题,但它用户体验问题。假设用户复制了一些东西,并认为他知道剪贴板上的内容,然后浏览您的网站,突然剪贴板中包含他不需要的东西,他丢失了他最初复制的内容。【参考方案6】:

如果您想要一个非常简单的解决方案(集成时间不到 5 分钟)并且开箱即用看起来不错,那么Clippy 是一些更复杂解决方案的不错替代方案。

它是由 GitHub 的联合创始人编写的。示例 Flash 嵌入代码如下:

<object
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
    
    
    id="clippy">

    <param name="movie" value="/flash/clippy.swf"/>
    <param name="allowScriptAccess" value="always"/>
    <param name="quality" value="high"/>
    <param name="scale" value="noscale"/>
    <param NAME="FlashVars" value="text=#text"/>
    <param name="bgcolor" value="#bgcolor"/>
    <embed
        src="/flash/clippy.swf"
        
        
        name="clippy"
        quality="high"
        allowScriptAccess="always"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer"
        FlashVars="text=#text"
        bgcolor="#bgcolor"/>
</object>

记得将#text 替换为您需要复制的文本,并将#bgcolor 替换为颜色。

【讨论】:

对于任何感兴趣的人,请在复制 repo 的 URL 时检查在 GitHub 上使用的 Clippy。【参考方案7】:

我最近就这个问题写了technical blog post(我在 Lucidchart 工作,我们最近对剪贴板进行了大修)。

将纯文本复制到剪贴板相对简单,假设您尝试在系统复制事件期间执行此操作(用户按下 Ctrl + C 或使用浏览器的菜单) .

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie")    != -1 ||
            navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) 
    var textToPutOnClipboard = "This is some text";
    if (isIe) 
        window.clipboardData.setData('Text', textToPutOnClipboard);
     else 
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    
    e.preventDefault();
);

不在系统复制事件期间将文本放在剪贴板上要困难得多。看起来这些其他答案中的一些参考了通过 Flash 进行操作的方法,这是唯一的跨浏览器方法(据我了解)。

除此之外,还有一些基于浏览器的选项。

这是 Internet Explorer 中最简单的,您可以随时通过 JavaScript 访问 clipboardData 对象:

window.clipboardData

(但是,当您尝试在系统剪切、复制或粘贴事件之外执行此操作时,Internet Explorer 会提示用户授予 Web 应用剪贴板权限。)

在 Chrome 中,您可以创建一个 Chrome 扩展程序,该扩展程序将为您提供clipboard permissions(这就是我们为 Lucidchart 所做的)。然后对于安装了您的扩展程序的用户,您只需要自己触发系统事件:

document.execCommand('copy');

看起来 Firefox 有 some options 允许用户授予某些网站访问剪贴板的权限,但我个人没有尝试过这些。

【讨论】:

博文中没有提到(我希望在不久的将来更新它),是使用 execCommand 触发剪切和复制的能力。这在 IE10+、Chrome 43+ 和 Opera29+ 中受支持。在这里阅读它。 updates.html5rocks.com/2015/04/cut-and-copy-commands 这样做的一个问题是它劫持了其他正常的复制事件。 注意!这种浏览器嗅探很糟糕。做特征嗅探。你让 IE 很难更新。【参考方案8】:

我喜欢这个:

<input onclick="this.select();" type='text' value='copy me' />

如果用户不知道如何在其操作系统中复制文本,那么他们很可能也不知道如何粘贴。因此,只需自动选择它,其余的留给用户。

【讨论】:

我也喜欢它,因为它很短。也可以复制:&lt;input onclick="this.select(); document.execCommand('copy');" type='text' value='copy me' /&gt;【参考方案9】:

clipboard.js 是一个小型的非 Flash 实用程序,允许将文本或 HTML 数据复制到剪贴板。它非常易于使用,只需包含 .js 并使用如下内容:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() 
  clipboard.copy(
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  ).then(
    function()console.log('success'); ,
    function(err)console.log('failure', err);
  );

);
</script>

clipboard.js 也在GitHub。

注意:现在已弃用。迁移到here。

【讨论】:

这个库被 angular.io 用于其英雄之旅,并通过显示用户只需复制的预选文本以优雅模式回退不支持 execCommand 的浏览器。 看起来clipboard.js 已被替换或分叉,但它似乎仍然存在并在npmjs.com/package/clipboard 积极维护【参考方案10】:

在 2018 年,您可以这样做:

async copySomething(text?) 
  try 
    const toCopy = text || location.href;
    await navigator.clipboard.writeText(toCopy);
    console.log('Text or Page URL copied');
  
  catch (err) 
    console.error('Failed to copy: ', err);
  

它在我的 Angular 6+ 代码中使用如下:

<button mat-menu-item (click)="copySomething()">
    <span>Copy link</span>
</button>

如果我传入一个字符串,它会复制它。如果没有,它会复制页面的 URL。

也可以对剪贴板内容进行更多操作。在此处查看更多信息:

Unblocking Clipboard Access

【讨论】:

你已经链接到本地​​主机 请注意,这在 Safari(版本 11.1.2)中不起作用 @arjun27 希望有一天苹果能赶上。虽然这个caniuse.com/#feat=clipboard 显示了你提到的部分支持的上述版本。 我得到两个函数 readText, writeText 一个 Promise 处于拒绝状态 根据提供的链接,“navigator.clipboard 仅支持通过 HTTPS 提供的页面”【参考方案11】:

我使用它非常成功(没有 jQuery 或任何其他框架)。

function copyToClp(txt)
    var m = document;
    txt = m.createTextNode(txt);
    var w = window;
    var b = m.body;
    b.appendChild(txt);
    if (b.createTextRange) 
        var d = b.createTextRange();
        d.moveToElementText(txt);
        d.select();
        m.execCommand('copy');
     
    else 
        var d = m.createRange();
        var g = w.getSelection;
        d.selectNodeContents(txt);
        g().removeAllRanges();
        g().addRange(d);
        m.execCommand('copy');
        g().removeAllRanges();
    
    txt.remove();

警告

制表符被转换为空格(至少在 Chrome 中)。

【讨论】:

无法在 firefox 上运行,我收到一条错误消息,提示缺少用户激活 @Luke_ Firefox 对吗?您是否在没有用户直接点击的情况下调用它?【参考方案12】:

ZeroClipboard 是我发现的最好的跨浏览器解决方案:

<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>
<script src="ZeroClipboard.js"></script>
<script>
  var clip = new ZeroClipboard( document.getElementById('copy') );
</script>

如果您需要对 ios 的非 Flash 支持,您只需添加一个备用:

clip.on( 'noflash', function ( client, args ) 
    $("#copy").click(function()
        var txt = $(this).attr('data-clipboard-text');
        prompt ("Copy link, then click OK.", txt);
    );
);

http://zeroclipboard.org/

https://github.com/zeroclipboard/ZeroClipboard

【讨论】:

使用 Flash 跨浏览器?不适用于 iOS 和 android 4.4 查看更新的答案。这允许 Flash 用户的步骤更少,并为其他所有人提供后备。 它有十亿行代码。这绝对是嘲笑。最好不要在项目中包含这样的怪物 有一个简单的版本gist.github.com/JamesMGreene/8698897 是 20K,它没有 74k 版本中的所有花里胡哨。两者都不是很大。我的猜测是大多数用户都可以接受下载 74k 或 20k 文件所花费的额外毫秒数,因此复制/粘贴只需单击一次而不是两次。 @Justin 我无法让它在本地工作,即使我复制和粘贴示例(我做了最小的更改,例如脚本标签中src 的值)。我觉得他们的文档很漂亮但效率低下。【参考方案13】:

由于 Chrome 42+ 和 Firefox 41+ 现在支持 document.execCommand('copy') 命令,我使用Tim Down's old answer 和 Google Developer's answer 的组合:

function selectElementContents(el) 
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) 
        // Internet Explorer
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
        textRange.execCommand("Copy");
    
    else if (window.getSelection && document.createRange) 
        // Non-Internet Explorer
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        try 
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copy command was ' + msg);
        
        catch (err) 
            console.log('Oops, unable to copy');
        
    
 // end function selectElementContents(el)

function make_copy_button(el) 
    var copy_btn = document.createElement('input');
    copy_btn.type = "button";
    el.parentNode.insertBefore(copy_btn, el.nextSibling);
    copy_btn.onclick = function() 
        selectElementContents(el);
    ;

    if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) 
        // Copy works with Internet Explorer 4+, Chrome 42+, Firefox 41+, Opera 29+
        copy_btn.value = "Copy to Clipboard";
    
    else 
        // Select only for Safari and older Chrome, Firefox and Opera
        copy_btn.value = "Select All (then press Ctrl + C to Copy)";
    

/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy,
    but there was a bug in Chrome versions 42 to 47 that makes it return "false".  So in those
    versions of Chrome feature detection does not work!
    See https://code.google.com/p/chromium/issues/detail?id=476508
*/

make_copy_button(document.getElementById("markup"));
<pre id="markup">
  Text that can be copied or selected with cross browser support.
</pre>

【讨论】:

感谢您的总结!您的代码中有一些错误:您定义了两次“范围”变量(var range = document.createRange())。 你是对的@ChristianEngel。我已经删除了第二个。我不知道它是怎么进来的。 您好,杰夫,如果我想自定义“复制到剪贴板”怎么办。请帮忙!【参考方案14】:

    $("td").click(function (e) 
        var clickedCell = $(e.target).closest("td");
        navigator.clipboard.writeText(clickedCell.text());
        alert(clickedCell.text());
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>First<td>
</tr>
<tr>
<td>Second<td>
</tr>
<tr>
<td>Third<td>
</tr>
<tr>
<td>Fourth<td>
</tr>
</table>

我已阅读所有答案,截至 2020 年 6 月 1 日,当我终于找到文档时,我一直在努力解决这个问题:

$("td").click(function (e) 
    var clickedCell = $(e.target).closest("td");
    navigator.clipboard.writeText(clickedCell.text());
);

它将点击的单元格文本写入浏览器剪贴板。

您可以根据需要更改选择器“td”,您可以添加 console.log 以进行调试和/或警报功能。

这是文档: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText

【讨论】:

不兼容 IE【参考方案15】:

来自我一直从事的一个项目,一个利用 ZeroClipboard 库的 jQuery 复制到剪贴板插件。

如果你是一个重度 jQuery 用户,它比原生零剪贴板插件更容易使用。

【讨论】:

92kb 并没有那么大,它运行得很快,如果你愿意,你可以使用text() 而不是innerHTML().. @John: innerHTML 已经支持跨浏览器很长时间了。仅仅因为微软最初提出了这个想法,它并没有使它不可靠或专有。它现在也终于被添加到官方规范中(在每个主要浏览器供应商都已经添加了对它的支持之后......sigh)。 @John 你抱怨 jQuery 在使用 Flash 的答案中不够 JavaScript ;) innerHTML 在大多数情况下都比替代品好。下马!它更快、更高效,并且不需要重新渲染页面。 @RozzA 92KB 真的很大。直到LTE 成熟GPRS 是WW mobile data standard,它从1 KB/s 开始。自己算算。【参考方案16】:

我把我认为最好的放在一起。

使用 cssText 来避免 Internet Explorer 中的异常,而不是直接使用样式。 如果有选择,则恢复选择 设置为只读,这样键盘就不会出现在移动设备上 有一个适用于 iOS 的解决方法,这样它就可以正常工作,因为它通常会阻止 execCommand。

这里是:

const copyToClipboard = (function initClipboardText() 
  const textarea = document.createElement('textarea');

  // Move it off-screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) 
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmatic execCommand copying normally, without this hack.
    // https://***.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) 
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    
    else 
      textarea.select();
    

    try 
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) 
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      

      return result;
    
    catch (err) 
      console.error(err);
      return false;
    
  ;
)();

用法:copyToClipboard('some text')

【讨论】:

【参考方案17】:

我找到了以下解决方案:

on-key-down 处理程序创建一个“pre”标签。我们将要复制的内容设置到此标签,然后在此标签上进行选择并在处理程序中返回 true。这会调用 Chrome 的标准处理程序并复制选定的文本。

如果您需要,您可以为恢复先前选择的功能设置超时。我在MooTools 上的实现:

function EnybyClipboard() 
    this.saveSelection = false;
    this.callback = false;
    this.pastedText = false;

    this.restoreSelection = function() 
        if (this.saveSelection) 
            window.getSelection().removeAllRanges();
            for (var i = 0; i < this.saveSelection.length; i++) 
                window.getSelection().addRange(this.saveSelection[i]);
            
            this.saveSelection = false;
        
    ;

    this.copyText = function(text) 
        var div = $('special_copy');
        if (!div) 
            div = new Element('pre', 
                'id': 'special_copy',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            );
            div.injectInside(document.body);
        
        div.set('text', text);
        if (document.createRange) 
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) 
                this.saveSelection[i] = selection.getRangeAt(i);
            
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            setTimeout(this.restoreSelection.bind(this), 100);
         else return alert('Copy did not work. :(');
    ;

    this.getPastedText = function() 
        if (!this.pastedText) alert('Nothing to paste. :(');
        return this.pastedText;
    ;

    this.pasteText = function(callback) 
        var div = $('special_paste');
        if (!div) 
            div = new Element('textarea', 
                'id': 'special_paste',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            );
            div.injectInside(document.body);
            div.addEvent('keyup', function() 
                if (this.callback) 
                    this.pastedText = $('special_paste').get('value');
                    this.callback.call(null, this.pastedText);
                    this.callback = false;
                    this.pastedText = false;
                    setTimeout(this.restoreSelection.bind(this), 100);
                
            .bind(this));
        
        div.set('value', '');
        if (document.createRange) 
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) 
                this.saveSelection[i] = selection.getRangeAt(i);
            
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            div.focus();
            this.callback = callback;
         else return alert('Failed to paste. :(');
    ;

用法:

enyby_clip = new EnybyClipboard(); // Init

enyby_clip.copyText('some_text'); // Place this in the Ctrl+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) 
    alert(pasted_text);
); // Place this in Ctrl+V handler and return true;

在粘贴时,它会创建一个文本区域并以相同的方式工作。

PS:也许这个解决方案可以用来创建一个没有 Flash 的完整的跨浏览器解决方案。它适用于 Firefox 和 Chrome。

【讨论】:

有人试过吗?听起来很不错,以防它真的适用于一系列浏览器! jsfiddle.net/H2FHC 演示:fiddle.jshell.net/H2FHC/show 请打开它并按 Ctrl+V 或 Ctrl+C。在 FF 19.0 中完美分叉。在 Chrome 25.0.1364.97 m 中也是如此。歌剧 12.14 - 好的。适用于 Windows 的 Safari 5.1.7 - 好的。 IE - 失败。 对于 IE 需要在页面内的元素上运行焦点。请参阅 fiddle.jshell.net/H2FHC/3/show 和 fiddle.jshell.net/H2FHC/3 在 IE 9/10 中工作。 IE 6/7 需要以其他方式创建选择,因为不支持 document.createRange。【参考方案18】:

其他方法会将纯文本复制到剪贴板。要复制 HTML(即,您可以将结果粘贴到所见即所得的编辑器中),您可以在 Internet Explorer only 中执行以下操作。这与其他方法有根本的不同,因为浏览器实际上是在可见地选择内容。

// Create an editable DIV and append the HTML content you want copied
var editableDiv = document.createElement("div");
with (editableDiv) 
    contentEditable = true;

editableDiv.appendChild(someContentElement);

// Select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();
r.execCommand("Copy");

// Deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(someHiddenDiv);
r.select();

【讨论】:

在这里查看更完整的 HTML 解决方案***.com/questions/34191780/…【参考方案19】:

此代码已于 2021 年 5 月测试。在 Chrome、IE、Edge 上工作。下面的'message'参数是你要复制的字符串值。

<script type="text/javascript">
    function copyToClipboard(message) 
        var textArea = document.createElement("textarea");
        textArea.value = message;
        textArea.style.opacity = "0"; 
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();


        try 
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            alert('Copying text command was ' + msg);
         catch (err) 
            alert('Unable to copy value , error : ' + err.message);
        

        document.body.removeChild(textArea);
    

</script>

【讨论】:

【参考方案20】:

从 Flash 10 开始,如果操作源自用户与 Flash 对象的交互,则只能复制到剪贴板。 (Read the related section from Adobe's Flash 10 announcement.)

解决方案是在复制按钮或启动复制的任何元素上方覆盖 Flash 对象。 ZeroClipboard 是目前具有此实现的最佳库。经验丰富的 Flash 开发人员可能只想制作自己的库。

【讨论】:

【参考方案21】:

我找到了以下解决方案:

我在隐藏的输入中有文本。因为setSelectionRange 不适用于隐藏输入,所以我暂时将类型更改为文本,复制文本,然后再次将其隐藏。如果要从元素中复制文本,可以将其传递给函数并将其内容保存在目标变量中。

jQuery('#copy').on('click', function () 
    copyToClipboard();
);

function copyToClipboard() 
    var target = jQuery('#hidden_text');

    // Make it visible, so can be focused
    target.attr('type', 'text');
    target.focus();
    // Select all the text
    target[0].setSelectionRange(0, target.val().length);

    // Copy the selection
    var succeed;
    try 
        succeed = document.execCommand("copy");
    
    catch (e) 
        succeed = false;
    

    // Hide input again
    target.attr('type', 'hidden');

    return succeed;

【讨论】:

【参考方案22】:

已经有很多答案了,但是想添加一个(jQuery)。适用于任何浏览器,也适用于移动浏览器(即,关于安全性的提示,但当您接受它时,它就可以正常工作)。

function appCopyToClipBoard(sText)

    var oText = false,
        bResult = false;
    try
    
        oText = document.createElement("textarea");
        $(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
        oText.select();
        document.execCommand("Copy");
        bResult = true;
    
    catch(e) 
    

    $(oText).remove();
    return bResult;

在您的代码中:

if (!appCopyToClipBoard('Hai there! This is copied to the clipboard.'))

    alert('Sorry, copy to clipboard failed.');

【讨论】:

【参考方案23】:

将文本从 HTML 输入复制到剪贴板:

 function myFunction() 
   /* Get the text field */
   var copyText = document.getElementById("myInput");

   /* Select the text field */
   copyText.select();

   /* Copy the text inside the text field */
   document.execCommand("Copy");

   /* Alert the copied text */
   alert("Copied the text: " + copyText.value);
 
 <!-- The text field -->
 <input type="text" value="Hello Friend" id="myInput">

 <!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>

注意: Internet Explorer 9 及更早版本不支持document.execCommand() 方法。

来源:W3Schools - Copy Text to Clipboard

【讨论】:

【参考方案24】:

从(类似于 Excel)构建自定义网格编辑以及与 Excel 的兼容性时,我遇到了同样的问题。我必须支持选择多个单元格、复制和粘贴。

解决方案:创建一个文本区域,您将在其中插入数据以供用户复制(对我来说,当用户选择单元格时),将焦点设置在它上面(例如,当用户按下 Ctrl 时)并选择整个文本。

所以,当用户点击 Ctrl + C 时,他/她会得到他/她选择的复制单元格。测试后,只需将 textarea 的大小调整为一个像素(我没有测试它是否可以在 display:none 上工作)。它适用于所有浏览器,并且对用户透明。

粘贴 - 您可以这样做(因目标而异) - 将注意力集中在 textarea 上并使用 onpaste 捕获粘贴事件(在我的项目中,我使用单元格中的 textareas 进行编辑)。

我无法粘贴示例(商业项目),但你明白了。

【讨论】:

【参考方案25】:

这是其他答案之间的一点组合。

var copyToClipboard = function(textToCopy)
    $("body")
        .append($('<textarea name="fname" class="textToCopyInput"/>' )
        .val(textToCopy))
        .find(".textToCopyInput")
        .select();
      try 
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        alert('Text copied to clipboard!');
       catch (err) 
          window.prompt("To copy the text to clipboard: Ctrl+C, Enter", textToCopy);
      
     $(".textToCopyInput").remove();

它使用 jQuery,但它当然不是必须的。如果你愿意,你可以改变它。我只是有 jQuery 供我使用。您还可以添加一些 CSS 以确保不显示输入。例如:

.textToCopyInputopacity: 0; position: absolute;

当然你也可以做一些内联样式

.append($('<textarea name="fname" style="opacity: 0;  position: absolute;" class="textToCopyInput"/>' )

【讨论】:

如何直接从变量数据中复制。即:var str = "word"; ? 变量 msg 未使用 最好使用 '' 以防 textToCopy 包含 \n【参考方案26】:

在 Internet Explorer 以外的浏览器中,您需要使用一个小的 Flash 对象来操作剪贴板,例如

Auto copy to clipboard

【讨论】:

这已经过时了...查看 GvS 的建议 GvS的建议是用flash电影?这不是同一个想法吗?【参考方案27】:
function copytoclipboard(element) 

    var $temp = $("<input>");
    $("body").append($temp);
    $temp.val('0' + element).select();
    document.execCommand("copy");
    $temp.remove();

【讨论】:

谢谢你,你是救命稻草【参考方案28】:

我用过 clipboard.js。

我们可以在 npm 上得到它:

npm install clipboard --save

还有Bower

bower install clipboard --save

用法和示例位于https://zenorocha.github.io/clipboard.js/。

【讨论】:

我担心它与动态内容不兼容,但它是 ;-) 我认为它是比 2008 年的旧解决方案更好的解决方案。 他们说:"While Bower is maintained, we recommend using Yarn and Webpack or Parcel for front-end projects"【参考方案29】:

要将选定的文本(“要复制的文本”)复制到剪贴板,请创建一个 Bookmarklet(执行 JavaScript 的浏览器书签)并执行它(单击它)。它将创建一个临时文本区域。

来自 GitHub 的代码:

https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d

(function (text) 
  var node = document.createElement('textarea');
  var selection = document.getSelection();

  node.textContent = text;
  document.body.appendChild(node);

  selection.removeAllRanges();
  node.select();
  document.execCommand('copy');

  selection.removeAllRanges();
  document.body.removeChild(node);
)('Text To Copy');

【讨论】:

【参考方案30】:

这是 Chase Seibert's answer 的扩展,其优点是它适用于 IMAGE 和 TABLE 元素,而不仅仅是 Internet Explorer 9 上的 DIV。

if (document.createRange) 
    // Internet Explorer 9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // Does nothing on Firefox
 else 
    // Internet Explorer 8 and earlier. This stuff won't work
    // on Internet Explorer 9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table).
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');

【讨论】:

以上是关于如何在 JavaScript 中复制到剪贴板?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用javascript从多个div中仅复制一个DIV到剪贴板

使用JavaScript读取所选文本并将其复制到剪贴板

使用JavaScript读取所选文本并将其复制到剪贴板

使用 Javascript 选择一个完整的表(要复制到剪贴板)

复制到 jquery/javascript 中的剪贴板,没有 ipad / iphone 的 flash

使用javascript将自定义json对象复制到剪贴板