必须清洗零宽字符再写入剪贴板:用正则/\u200b-\u200f\u202a-\u202f\ufeff/g剔除不可见控制符,并归一化空白;ios乱码源于utf-8被误解析为latin-1,需确保服务端、文件、页面均为utf-8编码。

uni.setClipboardData 写入含零宽字符的字符串导致粘贴乱码
直接把微信转发来的口令、AI生成的代码块或富文本编辑器导出的内容传给 uni.setClipboardData,粘贴时出现空白、错位、换行丢失或“”符号,大概率是内容里混入了不可见控制字符,比如 \u200b(零宽空格)、\u200c(零宽非连接符)或 \uFEFF(BOM头)。
这些字符在控制台 console.log(res.data) 看着像空,但 res.data.length > 0;用 JSON.stringify() 一打就露馅:"\u200bHello"。
- 写入前必须清洗:用正则一次性剔除常见不可见字符:
text.replace(/[\u200b-\u200f\u202a-\u202f\uFEFF]/g, '') - 顺手归一化空白:
.replace(/[\r\n\t\s\u00A0]+/g, ' ').trim(),避免首尾空格或全角空格干扰粘贴效果 - 若来源是 HTML 字符串(如服务端返回的富文本),得先去标签:
.replace(/]*>/g, ''),再做上述两步
从微信/钉钉复制的口令读出来是空字符串
uni.getClipboardData 成功回调里 res.data === "",但用户明明刚复制了内容——这不是 API 失效,而是剪贴板里实际存的是带零宽字符的“伪空值”。微信、钉钉在分享链接或口令时会自动注入 \u200b 类字符用于防爬,它们不占显示宽度,却会让 .trim() 失效。
- 验证方式:打印
JSON.stringify(res.data),看到"\u200b123456"就确认了 - 清理必须用显式替换:
res.data.replace(/[\u200b-\u200f\u202a-\u202f\uFEFF]/g, '').trim() - 别只依赖
.trim():它对零宽字符完全无效;也别用.replace(/\s/g, ''),\s不匹配\u200b
iOS 真机粘贴中文显示为“文件”这类乱码
这和剪贴板 API 无关,是编码层面的问题:字符串本身在 JS 运行时就是 UTF-8 编码的,但某些原生层或目标应用(如备忘录、企业微信)错误地按 Latin-1 解析字节流,导致 UTF-8 的多字节序列被拆解成单字节乱码。
- 根本解法是确保输入源干净:服务端返回的 JSON 不要二次 encode;本地文件保存为 UTF-8(无 BOM);HBuilderX 中右键文件 → “以指定编码重新打开” → 选 UTF-8
- 避免在字符串拼接中混入 GBK 编码的本地资源(如旧版 txt 配置文件),这类文件读取后若未指定编码,Node.js 或原生层可能默认用系统编码解析
-
uni.setClipboardData本身不处理编码转换,它只原样写入 JS 字符串的 UTF-16 表示——只要 JS 字符串正确,乱码一定来自上游或下游
H5 端 navigator.clipboard.writeText 写入后粘贴仍是乱码
H5 使用原生 API 时,如果调用 navigator.clipboard.writeText('测试') 后粘贴出乱码,基本可锁定为页面 <meta charset> 缺失或错误,或响应头 Content-Type 未声明 charset=utf-8。
- 检查 HTML 模板是否包含:
<meta charset="UTF-8">(必须在最前面) - 若通过
uni-app的 H5 模板构建,确认vue.config.js或index.html没被手动改掉 charset - 本地开发时用
file://协议打开,浏览器可能忽略 meta 标签,务必走http://localhost启动服务验证











