navigator.clipboard.writeText() 写入失败的常见原因包括:非安全上下文(非HTTPS且非localhost)、非用户手势触发、异步延迟调用、iframe缺失allow="clipboard-write"属性、浏览器权限静默拒绝、文档未聚焦或标签页非活跃,以及Safari等浏览器需额外权限声明或不支持。
Clipboard API 写入失败的常见原因
调用
报错 “Failed to execute 'writeText' on 'Clipboard': Document is not focused or permission denied”,基本是因为当前上下文不满足安全要求:页面必须是 HTTPS(本地
除外),且调用必须由用户手势(如
、
)触发,不能在异步回调(如
、
)中直接调用。
如何正确调用 writeText() 并处理拒绝情况
必须包裹在用户事件监听器中,并显式捕获 Promise 拒绝。浏览器不会自动弹出权限提示,而是静默拒绝——只有首次调用时可能触发权限请求(取决于 UA 实现),但更常见的是直接 reject。
使用
,而非
或定时器
必须用
或
处理失败,例如用户禁用了剪贴板权限或处于 iframe 无权限上下文
不要假设
一定存在:Safari 13.1+ 和旧版 Android WebView 不支持,需降级到
(仅限文本)
示例:
writeText() 与 execCommand('copy') 的关键区别
是现代标准,支持跨域 iframe(若启用
权限策略),而
已废弃,依赖
临时聚焦和选中,兼容性好但行为不可靠。
立即学习
“
前端免费学习笔记(深入)
”;
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
只接受字符串,不能写 HTML 或富文本;如需写 HTML,得用
+
(目前仅 Chromium 系支持较好)
在 Firefox 87+ 和 Safari 中已完全移除,不能用于新项目
移动端 iOS Safari 对
支持稳定,但部分 Android WebView 仍需 fallback
权限策略与 iframe 场景下的注意事项
如果页面嵌在 iframe 中,父页面需显式声明
权限,否则子 frame 调用会直接被拒:
另外,某些浏览器(如 Chrome)对非活跃标签页的剪贴板写入会静默失败,即使有用户手势——这意味着切换标签后立即点击复制按钮,可能因页面未“激活”而失败。可监听
做状态提示,但无法绕过该限制。
真正容易被忽略的是:没有用户手势上下文时,连
都会失败,而写入失败往往比读取更难定位,因为错误信息太笼统,且不同浏览器返回的
不一致(
、
、
都可能出现)。
navigator.clipboard.writeText()http://localhostclickkeydownsetTimeoutfetch.thenbutton.addEventListener('click', async () => { ... })onloadtry/catch.catch()navigator.clipboarddocument.execCommand('copy')button.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText('Hello, world!');
console.log('Copied');
} catch (err) {
console.error('Copy failed:', err.name); // 可能是 'NotAllowedError' 或 'SecurityError'
}
});writeText()clipboard-writedocument.execCommand('copy')writeText()navigator.clipboard.write()ClipboardItemexecCommandwriteText()clipboard-writevisibilitychangeawait navigator.clipboard.readText()err.name'NotAllowedError''SecurityError''NotFoundError'