Overview
有三种主要浏览器API可用于复制到剪贴板:
Async 剪贴板API [navigator.clipboard.writeText]
?
- 截至2015年4月,大多数浏览器都支持此功能(请参见下面的浏览器支持).
- 访问是同步的,即停止页面中的JavaScript,直到完成,包括显示和用户与任何安全提示交互.
- 文本从DOM中读取并放在剪贴板上.
- 在2015年4月的测试期间,仅注意到Internet Explorer在写入剪贴板时显示权限提示.
覆盖复制事件
- See 剪贴板API documentation on 覆盖复制事件.
- 允许您修改任何复制事件中出现在剪贴板上的内容,可以包括纯文本以外的其他数据格式.
- 这里没有介绍,因为它没有直接回答问题.
General development notes
在控制台中测试代码时,不要期望剪贴板相关的命令起作用.通常,页面需要处于活动状态(异步剪贴板API)或需要用户交互(例如,用户单击)才能允许(document.execCommand('copy')
)访问剪贴板.有关详细信息,请参见下文.
IMPORTANT (noted here 2020/02/20)
请注意,由于本文最初是由deprecation of permissions in cross-origin IFRAMEs和其他IFRAME "sandboxing"编写的,因此嵌入式演示"运行代码片段"按钮和"codesen.io示例"无法在某些浏览器(包括Chrome和Microsoft Edge)上运行.
要开发和创建自己的网页,请通过HTTPS连接提供该网页,以进行测试和开发.
以下是演示代码工作的测试/演示页面:
https://deanmarktaylor.github.io/clipboard-test/个
Async + Fallback
由于浏览器对新的Async 剪贴板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>
(codesen.io示例可能不起作用,请阅读上面的"重要"说明)
请注意,此代码片段在Stack Overflow的嵌入式预览中不能很好地工作,您可以在此处try :https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011
Async 剪贴板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')
的支持有所增加,请参见下面的链接以获取浏览器更新:(102)?
简单的例子
(可能无法嵌入本网站,请阅读上面的"重要"注释)
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>
复杂示例:复制到剪贴板而不显示输入
如果屏幕上可见textarea
或input
元素,则上面的简单示例非常有用.
在某些情况下,您可能希望将文本复制到剪贴板,而不显示input
/textarea
元素.这是解决此问题的方法的一个示例(主要是插入元素、复制到剪贴板、删除元素):
使用谷歌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草案规范可在以下位置找到:
它是否受支持?
- 如果命令"受浏览器支持",则
document.queryCommandSupported('copy')
应返回true
.
- 如果现在调用
document.execCommand('copy')
将成功,则document.queryCommandEnabled('copy')
返回true
.判断以确保命令是从用户启动的线程调用的,并且满足其他要求.
然而,作为浏览器兼容性问题的一个例子,如果该命令是从用户启动的线程调用的,那么2015年4月~10月的Google Chrome仅从document.queryCommandSupported('copy')
返回true
.
请注意下面的兼容性细节.
浏览器兼容性详细信息
虽然简单地调用包装在try
/catch
挡路中的document.execCommand('copy')
(由于用户单击而调用)将使您获得最兼容的使用,但以下有一些附带条件:
任何拨打document.execCommand
document.queryCommandSupported
或document.queryCommandEnabled
时都应该用try
/catch
型挡路包装.
不同的浏览器实现和浏览器版本在调用时抛出不同类型的异常,而不是返回false
.
不同的浏览器实现仍在变化中,剪贴板API仍在草案中,因此请记住进行测试.