好久没写博客,太忙了。今天因为遇到复制文本的bug,在这里记录一下~
分析问题
起因是测试提了个不管:点击单号复制小图标,会报脚本错误。
报错信息显示的就是 TypeError: Cannot read properties of undefined (reading ‘writeText’)
但是我自己在本地测试时,是没有问题的,在demo网站也没有问题。
在我要了测试的ip地址去测试,发现确实是会报错。
在查看相关代码发现问题在于,navigator对象下是否有clipboard对象。
在翻阅MDN文档后,发现问题所在。这个Navigator的clipboard属性是有限制的,必须是在支持的浏览器和安全上下文中可用。那么像我们的本地localhost,和我刚才的demo网站是用https的这些都属于安全上下文,所以测试并没有问题。在测试的机器里,因为是自己的ip域,并不是https。这个功能就会失效,所以就会报错undefined了
我们可以通过window.isSecureContext来判断是否是安全上下文。
如何解决
1.代码兼容非安全域的写法。
在安全域下使用 navigator.clipboard 提升效率,非安全域退回到 document.execCommand(‘copy’); 保证功能一直可用。
const handleCopy = (val) => {
if (window.isSecureContext && navigator.clipboard) {
navigator.clipboard
.writeText(val)
.then(() => {
ElMessage({
showClose: false,
message: t('audit_center.other_source.success_copy'),
type: 'success',
});
})
.catch((err) => {
ElMessage({
showClose: false,
message: `${t('audit_center.other_source.fail_copy')}:${err}`,
type: 'error',
});
});
} else {
const copyElem = document.createElement('textarea');
let styles = copyElem.style;
styles.position = 'fixed';
styles.zIndex = '0';
styles.left = '-500px';
styles.top = '-500px';
copyElem.value = val;
document.body.appendChild(copyElem);
copyElem.focus();
copyElem.select();
let result = false;
result = document.execCommand('copy');
if (result) {
ElMessage({
showClose: false,
message: t('audit_center.other_source.success_copy'),
type: 'success',
});
copyElem.remove();
} else {
ElMessage({
showClose: false,
message: `${t('audit_center.other_source.fail_copy')}`,
type: 'error',
});
}
}
};
- 引用第三方库
社区上有很多开源的复制剪切的jS库可以使用,第三方库考虑的比较全面,兼容问题都会处理好。
vue3-clipboard
xe-clipboard
import { toClipboard } from '@soerenmartius/vue3-clipboard';
const handleCopy = (val) => {
toClipboard(val)
.then((res) => {
ElMessage({
showClose: false,
message: t('audit_center.other_source.success_copy'),
type: 'success',
});
})
.catch((err) => {
ElMessage({
showClose: false,
message: `${t('audit_center.other_source.fail_copy')}:${err}`,
type: 'error',
});
});
};