uni-app跨端复制需分平台实现:App和小程序用uni.setClipboardData,H5须用navigator.clipboard.writeText加execCommand降级,且必须用户手势触发、HTTPS环境及正确条件编译。

uni-app 的剪贴板功能在 Vue3 组合式 API 中不能直接用 uni.setClipboardData 一招通吃 —— 它在 H5 端静默失效,且必须区分平台执行不同逻辑。跨端复制必须手动 fallback,否则真机或浏览器里点不动、没报错、也不复制。
uni.setClipboardData 只在 App 和小程序生效
这个 API 是 uni-app 官方封装,但仅对 APP-PLUS(iOS/Android)和微信/支付宝等小程序有效;H5 环境下调用既不触发 success 也不抛错,直接“吞掉”请求。
- 传入非字符串(如
number、object)会静默转成空串,建议统一用String(text).trim()处理 - 小程序端需提前在
manifest.json中配置权限,例如微信要求添加"scope.writeClipboard" - App 端无需 HTTPS,但 H5 端
navigator.clipboard强制要求window.isSecureContext === true(即 HTTPS 或 localhost)
H5 端必须用 navigator.clipboard.writeText + 降级兜底
H5 复制受浏览器策略限制极严,不能跳过安全校验和用户手势约束。直接写 navigator.clipboard.writeText 在 HTTP 环境或异步回调中会抛 NotAllowedError。
- 务必前置判断:
if (navigator.clipboard && window.isSecureContext) - 降级方案仍需
document.execCommand('copy'),虽然已被废弃,但仍是目前兼容性最广的兜底手段 - 用
textarea临时插入时,iOS Safari 要求显式调用textarea.setSelectionRange(0, txt.length),否则复制失败 - 所有操作必须由 click/tap 等用户手势同步触发,不能包裹在
setTimeout、Promise.then里
Vue3 组合式 API 封装一个跨端 copy 函数
别在每个页面重复写 if-else,用一个返回 Promise 的组合函数统一封装,按平台条件编译 + 统一错误处理。
立即学习“前端免费学习笔记(深入)”;
function useCopy() {
const copy = async (text) => {
const txt = String(text || '').trim()
if (!txt) return Promise.reject('内容为空')
// #ifdef APP-PLUS || MP-WEIXIN || MP-ALIPAY
return new Promise((resolve, reject) => {
uni.setClipboardData({
data: txt,
success: () => resolve(true),
fail: reject
})
})
// #endif
// #ifdef H5
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(txt)
}
// 降级:临时 textarea + execCommand
const textarea = document.createElement('textarea')
textarea.value = txt
textarea.style.position = 'fixed'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
textarea.select()
textarea.setSelectionRange(0, txt.length) // iOS 必须
const result = document.execCommand('copy')
document.body.removeChild(textarea)
return Promise.resolve(result)
// #endif
}
return { copy }
}
在组件中使用:const { copy } = useCopy(),然后 @click="copy('hello')" 即可。
自动导入 ref / onMounted 后,别漏掉 uni 的条件编译语法
如果你已用 unplugin-auto-import 自动导入了 ref、onMounted 等,注意 uni 对象不会被自动引入 —— 它是运行时注入的全局对象,但条件编译块(如 #ifdef H5)必须原样保留,Vite 不会解析它们为 JS 语法。
- 条件编译标签必须顶格写,前后不能有空格或缩进,否则不生效
-
uni在 H5 环境下不存在,所以不能在公共逻辑里无条件调用uni.setClipboardData - 真机调试时,H5 模式走的是浏览器环境,不是模拟器,务必用真机或 HTTPS 本地服务测试
真正麻烦的不是写代码,而是验证——同一个复制按钮,在微信开发者工具、安卓 App、iOS Safari、Chrome 桌面版上行为可能全都不一样。每次改完,至少要在三端点一遍才敢发版。


















