uni-app跨端复制必须条件编译分平台实现:h5用navigator.clipboard.writetext+execcommand降级,小程序用uni.setclipboarddata,app用plus.android原生调用;否则报错或静默失败。

直接结论:uni-app 中封装统一复制工具类,必须用条件编译区分平台,H5 用 navigator.clipboard.writeText + 降级 execCommand,小程序用 uni.setClipboardData,App 用 plus.android 原生调用;不加平台判断会直接报错或静默失败。
为什么不能只写一个 uni.setClipboardData
因为该 API 仅在微信小程序、支付宝小程序等部分小程序平台可用,在 H5 和 App 端会抛出 undefined is not a function 错误;而 H5 的 navigator.clipboard 在 iOS Safari 旧版本和部分安卓 WebView 中不可用;App 端(尤其是 Android)必须通过 plus.android 调用系统剪贴板服务,否则无权限写入。跨端复制不是“写一次就能跑”,是“写三套逻辑再兜底”。
copyToClipboard 工具函数怎么写才真正可用
核心是用 #ifdef 条件编译隔离平台逻辑,同时 Promise 化返回结果,便于业务层 await 或 .then:
-
#ifdef MP-WEIXIN或#ifdef MP:调用uni.setClipboardData({ data: text }),注意它不返回值,需靠 success 回调 resolve -
#ifdef H5:优先走navigator.clipboard.writeText(text),失败后 fallback 到document.execCommand('copy')降级方案(创建临时textarea) -
#ifdef APP-PLUS:用plus.android.importClass拿到ClipboardManager,再 setPrimaryClip;iOS 需额外判断plus.ios并调用UIPasteboard.generalPasteboard().setValue - 所有分支都包裹
try/catch,捕获异常后统一 reject,并打印console.error方便调试
常见踩坑点:H5 降级方案失效、App 权限未声明、返回值不一致
三个高频问题必须手动处理:
- H5 降级时
textarea未focus()或未select(),导致execCommand('copy')返回 false —— 必须显式调用textarea.focus()和textarea.select() - Android App 端未在
manifest.json → "permissions"中声明"android.permission.WRITE_CLIPBOARD"(新版本 Android 要求),会导致静默失败 - 不同平台 resolve 的值类型不一致(小程序无返回值、H5 返回
undefined、App 返回true),建议统一 resolvetrue或boolean,避免业务层做类型判断
怎么挂载到全局并安全调用
不要在 main.js 里直接挂载裸函数,而是封装成对象属性再挂载到 uni.$tools 或 uni.$utils:
import { copyToClipboard } from '@/utils/clipboard.js'
uni.$utils = { copyToClipboard }
页面中调用时,务必检查返回值:
await uni.$utils.copyToClipboard('hello').catch(err => {
uni.showToast({ title: '复制失败', icon: 'none' })
})
别忽略 catch —— 尤其在 H5 下用户禁用剪贴板权限时,navigator.clipboard.writeText 会直接 reject,不处理就无任何反馈。
最易被忽略的是:H5 页面必须是 HTTPS 或 localhost 才能启用 navigator.clipboard,HTTP 站点下该 API 为 undefined,降级逻辑必须生效,不能假设它一定存在。











