Clipboard API 写入文本必须在用户手势(如 click)中调用,否则抛 NotAllowedError;读取需权限且 Safari 完全不支持 readText(),应优先尝试 writeText() 并 fallback 到 execCommand,读富文本仅 Chrome/Edge 稳定支持。
浏览器只允许在明确的用户交互(如 click、keydown)回调中调用 navigator.clipboard.writeText(),否则会直接拒绝并抛出 "NotAllowedError"。这不是兼容性问题,而是安全策略强制要求。
button 的 onclick 里,或 addEventListener('click', ...)
setTimeout、fetch 回调、DOMContentLoaded 或自动轮询中input 或 textarea 的 input 事件不算可靠手势,部分浏览器(如 Safari)仍可能拒绝navigator.clipboard.readText() 不仅需要用户手势,还依赖 clipboard-read 权限。现代浏览器会在首次调用时弹出权限提示,但用户可永久拒绝——此时 Promise 永远 pending 或直接 reject,不会 fallback 到旧方法。
try/catch 包裹,捕获 NotAllowedError 和 NotFoundError(后者表示剪贴板为空或无文本)readText() 总能成功;建议提供手动粘贴入口(如 + paste 事件)作为降级dom.events.asyncClipboard.readText 在 about:config 中启用(默认关闭);Safari 目前**完全不支持** readText()
虽然 document.execCommand() 已废弃,但在 Safari 和部分旧 Chrome/Firefox 中仍是唯一可行的写入方式。关键不是“要不要用”,而是“怎么安全兜底”。
navigator.clipboard.writeText(),失败后 fallback 到 execCommand 流程execCommand 需要临时创建并聚焦一个 textarea,内容设为待复制文本,再执行 select() + execCommand('copy')
textarea,避免影响页面语义和焦点管理function copyToClipboard(text) {
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
}
const el = document.createElement('textarea');
el.value = text;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
const success = document.execCommand('copy');
document.body.removeChild(el);
return Promise.resolve(success);
}如果要读取用户复制的带格式内容(比如从 Word 或网页复制的 HTML),得用 navigator.clipboard.read(),它返回 ClipboardItem 数组。但这项能力目前仅 Chrome/Edge 稳定支持,Firefox 未实现,Safari 完全不可用。
read() 返回的是异步迭代器,需用 for await...of 或 items[0].getType('text/html') 获取 Blobblob.text() 解析成字符串,再做 HTML 清洗(不能直接 innerHTML)实际项目里最易忽略的,是 Safari 对 readText() 的彻底缺席——它连权限提示都不弹。如果你的应用依赖读取剪贴板(比如表单预填充、代码片段提取),必须提前设计非 Clipboard API 的替代链路,而不是等线上报错才补漏。