1. 使用的到API
- document.execCommand
- Async Clipboard API
2. 具体实现
1. 功能实现
input
可以用来展示要复制的内容。- 尝试使用 navigator.clipboard.writeText 写入文本至操作系统剪贴板。
- 失败则调用 document.getSelection() 缓存用户已经选择(如果有的话)的内容。相关阅读【Selection】
- 选中input中的文本,然后使用 document.execCommand("copy") ,选中的文本就会进入剪贴板。
- 使用 Selection.addRange() 恢复原始选择的范围。相关阅读【Range】
<div class="copy-input">
<input id="copy-input" type="text" readonly value="http://www.baidu.com">
<button onclick="copyInput()">copy</button>
</div>
<script>
async function copyInput () {
const inputDom = document.querySelector("#copy-input");
try {
return await navigator.clipboard.writeText(inputDom.value);
} catch (error) {
console.error(error);
}
const selected =
document.getSelection().rangeCount > 0
? document.getSelection().getRangeAt(0)
: false;
inputDom.focus();
inputDom.select();
document.execCommand("copy");
inputDom.setSelectionRange(0, 0);
inputDom.blur();
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
}
</script>
2. 实现一个复制文本到剪贴板函数。
在【copyToClipboard】 的基础上加上了 navigator.clipboard.writeText 的调用。
- 新建一个
<textarea>
元素,把要复制的内容赋值给它,将其添加到HTML文档中。 - 调用 document.getSelection() 缓存用户已经选择(如果有的话)的内容。
- 使用
document.execCommand('copy')
复制到剪贴板。 - 从HTML文档中删除
<textarea>
元素。 - 使用 Selection.addRange() 恢复原始选择的范围。
const copyToClipboard = async str => {
try {
return await navigator.clipboard.writeText(str);
} catch (error) {
console.error(error);
}
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
const selected =
document.getSelection().rangeCount > 0
? document.getSelection().getRangeAt(0)
: false;
el.select();
document.execCommand('copy');
document.body.removeChild(el);
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
};
3. 扩展-复制图片
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem
async function writeClipImg() {
try {
const imgURL = 'https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg';
const data = await fetch(imgURL);
const blob = await data.blob();
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
console.log('Fetched image copied.');
} catch(err) {
console.error(err.name, err.message);
}
}
参考文档
- 提到了编辑器 【execCommand的问题以及替代方案思考】
- 阮一峰 【剪贴板操作 Clipboard API 教程】
- 30-seconds-of-code 【copyToClipboard】
- npm package 【Copy to clipboard】
- VS Code 【BrowserClipboardService】