uni.setClipboardData 必须显式声明 success/fail 回调,不支持 Promise 链式调用;H5 需用 navigator.clipboard.writeText 并确保 HTTPS 和用户手势触发;跨平台应自行封装 Promise,严格校验参数与触发时机。

uni.setClipboardData 的 success/fail 回调必须显式声明
这个 API 不会自动触发 Vue 响应式更新,也不返回 Promise(除非你手动封装),直接写 uni.setClipboardData({ data: 'xxx' }) 是没有回调的。必须显式传入 success 和 fail 函数,否则操作静默完成或失败,你完全感知不到。
常见错误是只写了 success,漏掉 fail,结果在 H5 或低版本小程序里复制失败却没提示;或者把回调写在 .then() 里——它根本不支持链式调用。
-
success回调会在剪贴板内容真正写入后触发,但不保证用户一定能粘贴成功(比如系统限制) -
fail回调在权限拒绝、参数非法、非用户手势触发等场景下触发,不是所有平台都进这里:App 端可能直接静默失败,H5 端可能抛错但不进fail - 回调函数内
this指向组件实例,可直接调用this.$refs.toast.show()或修改this.copyStatus
H5 平台无法用 uni.setClipboardData 回调,得自己 catch 错误
在 H5 上调用 uni.setClipboardData 会直接 fallback 到 fail 回调(官方行为),所以不能依赖它来判断 H5 复制成败。你得绕开 uni.,改用原生方案并自行处理 Promise 链。
最稳做法是:先判断平台,H5 单独走 navigator.clipboard.writeText(),用 .then() 和 .catch() 接收结果;降级 execCommand 时,document.execCommand('copy') 返回布尔值,需手动包装成 Promise。
- HTTPS 是硬性前提,HTTP 下
navigator.clipboard直接不可用,控制台报SecurityError -
writeText()必须在用户手势(如@click)同步上下文中调用,放setTimeout或异步请求后会失败 - 不要在
fail回调里再尝试execCommand,两者逻辑要拆开,避免嵌套判断混乱
跨平台封装时,Promise 化能统一回调风格
如果你希望所有平台都用 .then().catch() 写法,就得自己封装一层 Promise,不能直接依赖 uni.setClipboardData 的回调机制。
注意 Vue 2 和 Vue 3 对 uni API 的 Promise 封装行为不同:Vue 2 返回数组 [err, res],Vue 3 才是标准 then(res) / catch(err)。所以封装时最好自己 new Promise,避开框架差异。
- 封装函数返回
Promise<boolean></boolean>最实用,上层只关心“是否成功”,不用管平台细节 - App 端可用
plus.android原生调用,比uni.setClipboardData更可控,失败时也能抛出明确错误 - 别在 Promise 封装里混用
uni.showToast,它和复制操作无关,且小程序端自带轻提示,重复弹会影响体验
容易被忽略的“用户手势”和“空值校验”陷阱
无论哪个平台,只要不是用户点击、触摸等直接交互触发的调用,复制都会失败,且大概率不报错——这是上线后最常被漏测的点。
另一个高频坑是传了空值:undefined、null、空对象 {}、空字符串 '',全部导致静默失败。尤其从接口取数后没做 ?.toString() 或 ?? '' 判断。
- 务必在调用前加
if (!text || typeof text !== 'string') return Promise.resolve(false) - 不要在
mounted或onLoad里自动复制,必须绑定到@tap/@click事件处理器第一行 - 小程序真机调试时,
fail回调里的err.errMsg可能是"setClipboardData:fail system error",这种基本就是非手势触发


















