“暗号复制”本质是克制调用uni.setClipboardData+隐藏交互设计,需按navigator.clipboard→execCommand→uni.setClipboardData三级降级,并确保HTTPS/权限配置/用户手势触发。

uni-app 里所谓“暗号复制”,本质是用户点击某个非显眼区域(比如图标、小按钮、空白处)后,悄悄把预设文本塞进剪贴板,不弹 toast 或只做极简反馈。它不是新 API,而是 uni.setClipboardData 的克制用法 + 隐藏交互设计。
为什么直接用 uni.setClipboardData 会失败或没反应
多数“暗号复制”点下去没动静,根本原因不是逻辑错,而是环境卡死:
- 在 H5 端调用时,页面不是 HTTPS 或 localhost,
navigator.clipboard.writeText直接抛NotAllowedError,fail回调都不进 - 在微信小程序真机上,未在微信公众平台提交「剪贴板」权限声明,
fail里会返回errMsg: "setClipboardData:fail auth deny" - App 端(Android/iOS)未在
manifest.json中配置"permissions": ["scope.clipboardWrite"],老版本甚至会静默忽略 - 把
uni.setClipboardData写在mounted、setTimeout或异步请求的.then里,浏览器判定非用户手势触发,直接拦截
如何让“暗号”真正生效:三步降级策略
不能只依赖 uni.setClipboardData。必须按优先级顺序尝试三种方式,并在每一步都做容错:
- 先试原生
navigator.clipboard.writeText(H5 最新标准,支持 Promise,但 iOS Safari 13.4+ 才行) - 失败则 fallback 到
document.execCommand('copy')(需创建临时<textarea>并 focus,兼容旧安卓 WebView) - 最后兜底用
uni.setClipboardData(小程序和 App 主力通道,但 H5 下会退化为 noop)
示例封装函数(可直接复用):
export const copySecret = async (text) => {
if (!text || typeof text !== 'string') return false;
// 1. navigator.clipboard
if (navigator.clipboard) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (e) {
// NotAllowedError 或 ReadableStream 不可用等
}
}
// 2. execCommand fallback
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
const result = document.execCommand('copy');
document.body.removeChild(textarea);
return result;
} catch (e) {
document.body.removeChild(textarea);
return false;
}
};
“暗号”交互设计的关键细节
用户点的是个图标或空白区,你不能弹满屏 toast —— 这就不是暗号,是打扰。要收敛反馈:
- 成功后最多用
uni.showToast({ title: '✓', icon: 'none', duration: 800 }),字号小、消失快 - 避免在
success里再调uni.getClipboardData去验证——既慢又可能触发额外权限提示 - 如果“暗号”是长按触发(如某些客服页),记得绑定
@longpress而非@click,iOS 微信对 click 的剪贴板限制更严 - 复制内容含 emoji 或中文,H5 下建议先
encodeURIComponent,粘贴端再decodeURIComponent,避免截断
最易被忽略的一点:H5 端的“暗号”必须运行在安全上下文(HTTPS / localhost),否则连降级逻辑都走不到 navigator.clipboard 分支,直接跳到 execCommand。开发时 localhost 没问题,上线后 HTTP 域名必挂,别等用户反馈才想起配证书。


















