Safari浏览器如何实现Javascript复制到剪贴板?

27

这可能是重复的问题,但我没有找到解决方案。

我正在尝试在单击按钮时复制文本。它在谷歌浏览器、火狐浏览器(在Windows和Mac上都可以工作,但在Linux上不能工作)中工作。而且它在Safari上不起作用。

我正在使用document.execCommand("copy")命令进行复制。

Safari支持这个命令吗?

有没有一种方式可以支持所有浏览器?


请查看此问题:js复制到剪贴板 - Kevin Kloet
7个回答

28

请检查我的解决方案。

它在Safari上运行正常(在iPhone 7和iPad上测试过),并且在其他浏览器上也可以。

window.Clipboard = (function(window, document, navigator) {
    var textArea,
        copy;

    function isOS() {
        return navigator.userAgent.match(/ipad|iphone/i);
    }

    function createTextArea(text) {
        textArea = document.createElement('textArea');
        textArea.value = text;
        document.body.appendChild(textArea);
    }

    function selectText() {
        var range,
            selection;

        if (isOS()) {
            range = document.createRange();
            range.selectNodeContents(textArea);
            selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            textArea.setSelectionRange(0, 999999);
        } else {
            textArea.select();
        }
    }

    function copyToClipboard() {        
        document.execCommand('copy');
        document.body.removeChild(textArea);
    }

    copy = function(text) {
        createTextArea(text);
        selectText();
        copyToClipboard();
    };

    return {
        copy: copy
    };
})(window, document, navigator);

// How to use
Clipboard.copy('text to be copied');

https://gist.github.com/rproenca/64781c6a1329b48a455b645d361a9aa3 https://fiddle.jshell.net/k9ejqmqt/1/

希望这些能帮到您。

敬礼。


{btsdaf} - Rodrigo
1
谢谢,这很有用。我不得不稍微调整一下以适应我的要求。浏览器检测代码在Mac上无法正常工作(很容易修复)。此外,在我的iPhone上,当调用此代码时,键盘会弹出。也有一个简单的方法解决这个问题(将焦点返回到触发复制的元素)。 - Mmm
你能为这个激活 Fiddle 吗? - Cristal
提到的演示链接处于非活动状态。您能否激活它? - Mohanraj Periyannan

8

最近我遇到了同样的问题,发现以下解决方法:

document.execCommand("copy")在Safari中现在可以正常工作。

如果您发现只有在Safari中复制命令无法正常工作,请检查是否将复制命令运行在API回调函数或其他类似异步方式中。同时,只有来自DOM事件的复制才能在Safari中工作,控制台测试无效。

对于我来说,要复制的文本来自异步调用的响应。我不得不将API调用移出onClick以预取文本,并且只有在单击复制按钮时才复制该文本。 非常好用!

如果直接将以下代码写入DOM事件处理程序(如onClick),则在Safari中可以正常工作:

var clipBoardElem = document.createElement("input");
document.body.appendChild(clipBoardElem);
clipBoardElem.value = "text";
clipBoardElem.select();
var successfulCopy = document.execCommand('copy');

完成后,您可以删除临时元素:
document.body.removeChild(clipBoardElem)

2
execCommand("copy")lib.dom.d.ts 中被标记为已弃用。 - TheAlphaGhost

7

现在,在这个问题四年之后,

Safari添加了剪贴板API!

现在你可以在 Safari 上(iOS 版本 13.4 及以上和桌面版版本 13.1 及以上)写入和读取文本以及任何任意数据到剪贴板上。

关于剪贴板的MDN文档Clipboard 接口实现了剪贴板 API,如果用户授权,提供对系统剪贴板内容进行读取和写入的访问权限。剪贴板 API 可用于在 Web 应用程序中实现剪切、复制和粘贴功能。

以下是如何实现你想要的功能:

navigator.clipboard.writeText("YOUR_TEXT").then(function() {

  /* clipboard successfully set */

}, function() {

  /* clipboard write failed */

});

3
我认为他们最终意识到一些开发者可能需要这个功能。 - Mahdi
我刚在iOS 14.4.2(iPhone 8)上尝试了一下,它运行良好。此外,根据caniuse.comMDN,Safari 14支持该功能。@HoangMinh - mohammadavood
@HoangMinh,我也遇到了你说的同样问题,你有没有找到解决办法? - kishore
2
@kishore:抱歉回复晚了。这是苹果设置的限制之一,如果没有用户交互,值将不会被复制。没有任何绕过这个限制的方法。基本上,你需要遵循他们的规则。我们所做的是添加一个UI输入框,显示您想要复制的值,并在旁边放置复制按钮。当点击按钮时,该值将被复制。 - Hoang Minh
2
Safari 15.4无法将您的代码片段复制到剪贴板。可能是苹果公司移除了此功能? - TheAlphaGhost
显示剩余2条评论

5
因为第一个答案在 iPhone 10 Safari 上对我不起作用,因此我尝试寻找其他解决方案,并在这里找到了一个描述:这里 基本上它提供了一个非常相似的解决方案,但是语法不同:
支持 "IE 10+, Chrome 43+, Firefox 41+ 和 Opera 29+"

var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
  // Select the email link anchor text  
  var emailLink = document.querySelector('.js-emaillink');
  var range = document.createRange();
  range.selectNode(emailLink);
  window.getSelection().addRange(range);

  try {
    // Now that we've selected the anchor text, execute the copy command  
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copy email command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  // Remove the selections - NOTE: Should use
  // removeRange(range) when it is supported  
  window.getSelection().removeAllRanges();
});
body {
  padding: 10px;
}
<p>Email me at <a class="js-emaillink" href="mailto:chriscoyier@gmail.com">chriscoyier@gmail.com</a></p>

<p><button class="js-emailcopybtn">Copy Email</button></p>

这段文字提到了一个叫做clipboardjs的库,看起来非常不错。

在我的情况下,这个简单的JS代码可以在以下设备上运行:

  • iPhone 10 Safari
  • chrome (android / pc (67.0.3396.79))
  • opera (pc (53.0.2907.68))

但是,它不能在以下设备上运行:

  • pc / android Firefox (60.0.1 (64-bit))

对于Firefox,简单的选择和复制就能搞定。

element.select();
document.execCommand('copy');

5

我发现在Safari中,在执行document.execCommand()之前需要选择文本。

此外,其他浏览器不支持addRange() (在Chrome中已弃用),这意味着有时它无法正确地合并选择和范围。这对用户体验的影响是,用户需要在Safari中点击两次才能复制值。在添加范围之前添加.removeAllRanges()将有助于确保您获取正确的选择以进行复制。不清楚是否仍需要第二个.removeAllRanges(),但为了安全起见我还是保留了它。

 copy(id) {
    var configId = document.querySelector(id);
    var range = document.createRange();
    range.selectNode(configId);
    var selection = window.getSelection()
    selection.removeAllRanges();
    selection.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');
    }

    selection.removeAllRanges();
  }

在同一类中使用:

<Button icon="copy" onClick={() => {this.copy(id)}}/>

id 可以是任何html选择器。

这在Chrome和Safari中对我有效。


这是在 React.js 的上下文中吗? - Brimby
@Brimby,“To use”在React按钮内部,但复制功能是纯JS。 - dwen
我认为为了回答这个问题,你应该将按钮重新格式化为纯HTML,并使用vanilla js监听器,或者写上“这里是由一个react.js组件调用的”,这样那些不太了解js或react的人就不会感到困惑了。 - Brimby

0
我曾经遇到过同样的问题 - 原来是因为我创建了一个临时的 select 元素来复制文本,这没问题,但我还通过各种方法将其隐藏起来,罪魁祸首是 element.style.width = 0。移除它并使用其他方法来隐藏它解决了我的问题。
希望这能帮助到遇到同样问题的人。

0
根据CanIUse的数据,iOS上的Safari不支持document.execCommand('copy'),可能是因为安全原因。

1
所以,对于所有浏览器来说,“复制到剪贴板”的最佳方法是什么,或者我们如何在Safari中实现此功能呢? - Akshay Deshmukh
1
如果你不知道,@Mahi的clipboardjs实际上是使用document.execCommand('copy')实现的。请查看源代码。 - Munim
截至版本10,document.execCommand('copy')在Safari上无法正常工作。 - Jair Reina
有没有Safari的替代品?我们有一个内部内容管理应用程序,其中我们为营销设置了一些HTML模板,它们都使用带有Safari的Mac... 让他们使用Chrome很困难。 - jeffcodes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接