微信 H5 页面兼容性——复制到剪贴板
在开发微信 H5 页面时,时常会遇到难以解决的兼容性问题,现收集问题和解决方案,以备后用。
在 PC 浏览器和手机移动端浏览器中,Web API 提供了两种方式:
1.1. Document.execCommand()
方法
Document.execCommand()
是操作剪贴板的传统方法,各种浏览器都支持。
它支持复制、剪切和粘贴这三个操作。
- document.execCommand('copy')(复制)
- document.execCommand('cut')(剪切)
- document.execCommand('paste')(粘贴)
缺点:
- 它只能将选中的内容复制到剪贴板,无法向剪贴板任意写入内容。
- 它是同步操作,如果复制/粘贴大量数据,页面会出现卡顿。
- 有些浏览器还会跳出提示框,要求用户许可,这时在用户做出选择前,页面会失去响应。
1.2. 异步 Clipboard API
优点:
- 它的所有操作都是异步的,返回 Promise 对象,不会造成页面卡顿。
- 可以将任意内容(比如图片)放入剪贴板。
Clipboard.readText()
方法用于复制剪贴板里面的文本数据。Clipboard.read()
方法用于复制剪贴板里面的数据,可以是文本数据,也可以是二进制数据(比如图片)。Clipboard.writeText()
方法用于将文本内容写入剪贴板。Clipboard.write()
方法用于将任意数据写入剪贴板,可以是文本数据,也可以是二进制数据。
在微信浏览器中,安卓设备和苹果设备操作复制功能,会出现下面的兼容性问题:
Clipboard.write()
不能正确复制富文本内容(比如包含换行的内容)。
安卓设备复制失败,报错 NotAllowedError: Write permission denied
(写权限被拒绝)。
苹果设备复制出来的内容不对包含了一些 html 标签。
Clipboard.write()
不能处理富文本内容,选用了vue-clipboard3
插件
vue-clipboard3
可以处理富文本内容,换行通过 \n
实现。
使用方式:
- 第一步:安装
vue-clipboard3
- 第二步:在需要使用的页面导入:
import useClipboard from 'vue-clipboard3';
- 第三步:实例化
useClipboard
,取到toClipboard
对象。 - 第四步:
toClipboard
是一个异步方法,使用await toClipboard(copyInfo)
实现复制到剪贴板。
通过 vue-clipboard3
安卓设备能正常复制。
IOS 复制不了跨域的超链接。
vue-clipboard3
不能处理苹果设备跨域复制超链接,选用document.execCommand('copy')
方法
document.execCommand('copy')
只能用于将选中的内容复制到剪贴板,需要模拟选中的操作:
export const copyText = (text: string) => {
// 数字没有 .length 不能执行selectText 需要转化成字符串
const textString = text.toString();
const input = document.createElement('input');
input.id = 'copy-input';
input.readOnly = true; // 防止ios聚焦触发键盘事件
input.style.position = 'absolute';
input.style.left = '-1000px';
input.style.zIndex = '-1000';
document.body.appendChild(input);
input.value = textString;
// ios必须先选中文字且不支持 input.select();
selectText(input, 0, textString.length);
input.blur();
document.body.removeChild(input); // 使用完成后,移除 input 元素,避免占用页面高度
// input自带的select()方法在苹果端无法进行选择,所以需要自己去写一个类似的方法
// 选择文本。createTextRange(setSelectionRange)是input方法
function selectText(textBox, startIndex: number, stopIndex: number) {
if (textBox.createTextRange) {
//ie
const range = textBox.createTextRange();
range.collapse(true);
range.moveStart('character', startIndex); //起始光标
range.moveEnd('character', stopIndex - startIndex); //结束光标
range.select(); //不兼容苹果
} else {
//firefox/chrome
textBox.setSelectionRange(startIndex, stopIndex);
textBox.focus();
}
}
console.log(document.execCommand('copy'), 'execCommand');
if (document.execCommand('copy')) {
document.execCommand('copy');
showSuccessToast('复制成功');
}
};
- 通过调用 copyText 自定义函数不能复制到剪贴板
直接调用函数 copyText(link) 不能实现复制,需要用户操作后,比如点了某一按钮再调用 函数 copyText(link)。例如在 vant4(轻量、可定制的移动端组件库)中,点弹框复制
按钮时调用:
showDialog({
confirmButtonColor: '#07d08c',
confirmButtonText: '复制',
showCancelButton: false,
message: '录制已完成,您可将下载地址复制到剪切板,在浏览器中粘贴地址进行下载',
}).then(() => {
copyText(link);
});
欢迎写出你的看法,一起成长!