两种复制到剪贴板的方法
方法一:navigator.clipboard.writeText()(现代 Clipboard API)
原理
通过浏览器提供的异步 Clipboard API 实现,基于 Promise 操作剪贴板。
特点
- 异步操作不阻塞主线程
- 需要 HTTPS 或 localhost 安全上下文
- API 简洁现代,代码量少
- 必须在用户交互事件中触发
代码实现
javascript
// Promise 写法
navigator.clipboard.writeText('要复制的文本')
.then(() => console.log('复制成功'))
.catch(err => console.error('复制失败:', err))
// async/await 写法
async function copyText(text) {
try {
await navigator.clipboard.writeText(text)
console.log('复制成功')
} catch (err) {
console.error('复制失败:', err)
}
}
浏览器支持
Chrome 66+、Firefox 63+、Safari 13.1+、Edge 79+
方法二:execCommand(传统实现)
原理
通过创建临时 <textarea> 元素,使用已废弃但广泛兼容的 document.execCommand('copy') 实现。
实现流程
- 创建隐藏的文本域元素
- 设置文本内容并添加到 DOM
- 选中文本内容
- 执行复制命令
- 清理 DOM 并恢复焦点
代码实现
javascript
function copyTextToClipboard(text) {
// 1. 创建临时 textarea 元素
const element = document.createElement('textarea')
const previouslyFocusedElement = document.activeElement
// 2. 设置文本内容
element.value = text
element.setAttribute('readonly', '')
// 3. 隐藏元素(不显示在页面上)
element.style.contain = 'strict'
element.style.position = 'absolute'
element.style.left = '-9999px'
element.style.fontSize = '12pt' // 防止 iOS 缩放
// 4. 保存当前选择状态
const selection = document.getSelection()
const originalRange = selection.rangeCount > 0 && selection.getRangeAt(0)
// 5. 添加到 DOM 并选中
document.body.append(element)
element.select()
element.selectionStart = 0
element.selectionEnd = text.length
// 6. 执行复制命令
let isSuccess = false
try {
isSuccess = document.execCommand('copy')
} catch (err) {
console.error('复制失败:', err)
}
// 7. 清理:移除元素,恢复选择状态和焦点
element.remove()
if (originalRange) {
selection.removeAllRanges()
selection.addRange(originalRange)
}
if (previouslyFocusedElement) {
previouslyFocusedElement.focus()
}
return isSuccess
}
特点
- 同步执行立即返回结果
- 兼容 IE 等老旧浏览器
- 实现复杂度较高
- 已被现代标准标记为废弃
渐进增强策略
推荐实现方案
javascript
function safeCopyText(text) {
if (navigator.clipboard?.writeText) {
return navigator.clipboard.writeText(text)
.catch(() => copyTextToClipboard(text))
}
return copyTextToClipboard(text)
}
优势
- 现代浏览器优先使用标准 API
- 自动降级保证兼容性
- 统一的错误处理机制
注意事项
- 所有复制操作必须由用户交互触发
- 建议添加成功/失败状态提示
- 测试需覆盖不同浏览器环境