uni.setClipboardData是最简单可控的跨端复制方案,但需满足用户点击事件第一层调用、参数为字符串、App端配置权限、小程序声明scope权限;H5端须降级至navigator.clipboard或execCommand兜底,并严守HTTPS、手势触发及时效性约束。

直接用 uni.setClipboardData 复制链接或文本是最简单、最可控的“数据分享”方式——它不依赖第三方 SDK,也不需要用户授权弹窗,只要点一下,内容就进剪贴板了,用户可自行粘贴到微信、钉钉、短信等任意地方。
uni.setClipboardData 在 App 和小程序里怎么写才不静默失败
这个 API 表面简单,但错一个条件就完全没反应,连错误都不报:
- 必须在用户点击事件的第一层回调里调用,比如
@tap="handleCopy"中的handleCopy函数体开头就执行;放进setTimeout、Promise.then或this.$nextTick里会失效 -
data参数只能是字符串,传number、object、null或undefined会转成空串或[object Object],务必先String()或JSON.stringify() - App 端要提前配权限:iOS 在
manifest.json→「App 设置」→「iOS 设置」勾选「剪贴板」;Android 在「模块权限配置」启用clipboard模块 - 小程序端(微信/支付宝)需在
manifest.json中声明权限,如微信要求配置"scope.writeClipboard"
H5 端复制必须绕过三个硬限制
uni.setClipboardData 在 H5 完全不支持,强行调用会静默失败。必须降级到浏览器原生方案,并处理以下约束:
-
navigator.clipboard.writeText只在 HTTPS 环境下可用,本地http://localhost会抛NotAllowedError;开发时建议用https://localhost或真机调试 - 必须由用户手势(
click、tap)直接触发,不能在异步回调中调用 - 旧版安卓 WebView(如 UC、QQ 浏览器)不支持
navigator.clipboard,得 fallback 到document.execCommand('copy')—— 虽已废弃,但仍是目前兼容性最广的兜底手段 - 用
execCommand时,必须创建临时textarea,调用.select()后再立即执行.setSelectionRange(0, txt.length),否则 iOS Safari 会失败
怎么封装一个真正能用的跨端 copy 函数
别写 if-else 拼平台,用 uni-app 条件编译 + 统一 Promise 接口更稳:
// utils/copy.js
export function copyText(text) {
if (!text || typeof text !== 'string') return Promise.reject('invalid text');
// #ifdef APP-PLUS || MP
return new Promise((resolve, reject) => {
uni.setClipboardData({
data: text,
success: () => resolve(),
fail: (err) => reject(err)
});
});
// #endif
// #ifdef H5
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
} else {
const input = document.createElement('textarea');
input.value = text;
input.setAttribute('readonly', '');
input.style.position = 'absolute';
input.style.left = '-9999px';
document.body.appendChild(input);
input.select();
input.setSelectionRange(0, text.length);
let result = false;
try {
result = document.execCommand('copy');
} catch (e) {}
document.body.removeChild(input);
return result ? Promise.resolve() : Promise.reject('execCommand failed');
}
// #endif
}
调用时统一用 copyText('https://example.com?ref=share').then(...).catch(...) 即可,不用每处都判平台。
最容易被忽略的一点:H5 的 navigator.clipboard 不仅要 HTTPS,还要页面处于活跃状态(比如没被切到后台),且用户交互后 5 秒内必须完成调用——超时就会拒绝。所以复制逻辑一定要紧贴点击事件,别加任何延迟或中间状态处理。


















