JavaScript `document.execCommand('copy')` 显示成功(returns `true`),但不向剪贴板写入任何内容

JavaScript `document.execCommand('copy')` appears successful (returns `true`), but does not write anything to clipboard

我试图在用户单击按钮时将文本值从隐藏元素复制到用户剪贴板。

我正在使用 ES6,使用 Webpack 和 Grunt 进行处理。

这些是我用来参考的文章:

MDN: Interact with the clipboard

Google: Cut and Copy Commands

我正在使用 document.execCommand('copy')。我还不知道这种方法有任何浏览器兼容性问题。

这是相关的标记:

<div class="icon-link">
  <a href="">
    <svg id="copy_button" ... /></svg>
  </a>

  <p id="copy_confirm">Copy Link</p>
</div>

...

<p id="copy_text" style="display:none;">[text content to copy]</p>

这里是相关的 JavaScript:

const copyBtn = document.getElementById('copy_button');
const copyText = document.getElementById('copy_text');

const copyLink = (e) => {
  e.preventDefault();

  const range = document.createRange();
  range.selectNode(copyText);
  window.getSelection().addRange(range);

  try {
    const successful = document.execCommand('copy');

    const msg = successful ? 'successful' : 'unsuccessful';
    global.console.log(`Copy command was ${msg}`);
  } catch (err) {
    global.console.log('Oops, unable to copy');
  }

  window.getSelection().removeAllRanges();
};

doc.addEventListener('DOMContentLoaded', () => {
  copyBtn.addEventListener('click', copyLink);
});

当我单击该按钮时,我在控制台中看到 "successful" 消息。我可以在控制台中通过 运行 手动验证此代码选择元素并执行 document.execCommand('copy') returns true

但是我剪贴板的内容没有改变。

我已验证页面正在呈现,隐藏元素中的文本值正确。

我试过将标记的结构更改为不同的元素类型,并更改样式以显示元素而不是隐藏它;这些都没有效果。

我已经尝试使用上面 MDN 文章中的 Element.select() 方法和 Google 文章中的基于 Range 的方法(此处显示);两者表现出相同的行为。

我看到了一些关于使用 document.execCommand() 的其他问题,但它们似乎都处理与函数返回 false 相关的问题。我还没有找到任何解决我所看到的行为的方法。

我最近在 Chrome 和 Firefox 中测试过。

你能帮我理解为什么我的剪贴板的内容没有改变吗?

今天我一定尝试了一些与我之前从可见字段复制的尝试略有不同的尝试;问题现已解决。

这是我正在使用的标记:

<div class="icon-link copy-link">
  <a href="">
    <svg id="copy_button" ... /></svg>
  </a>

  <p id="copy_confirm">Copy Link</p>
</div>

<input id="copy_text" type="text" value="[text content to copy]"/>

并且在 JavaScript 中,Element.select()range.selectNode() 方法似乎都可以正常工作。我从上面保留不变。

对于任何好奇的人,我现在用 transform: translateX(); 和一个非常大的负值隐藏 <input> 元素。