问题描述
最近有个需求功能为点击页面按钮复制文本到剪切板,实现一个快速复制的功能。但在本地调试一切正常,发布到测试环境,无法复制,打开控制台报错:
Cannot read properties of undefined (reading 'writeText')
问题分析
经查找资料发现是浏览器禁用了非安全域的 navigator.clipboard
对象,在控制台下执行 navigator.clipboard
返回的是 undefined。
那么哪些是安全域呢?
安全域包括本地访问与开启TLS安全认证的地址,如 https 协议的地址、127.0.0.1 或 localhost 。
所以我们现在就是作一个兼容写法来处理,在安全域下使用 navigator.clipboard 提升效率,非安全域退回到 document.execCommand('copy'); 保证功能可用。
代码如下
<template>
<span class="copy">
{{ data || '-' }}
<el-button @click="copy">复制</el-button>
</span>
</template>
<script>
export default {
name: 'CusCopy',
props: {
data: {
type: String,
default: ''
}
},
data() {
return {
}
},
mounted() {},
methods: {
copy() {
if(!this.data){
this.$message.error('数据为空')
return
}
this.copyToClipboard(this.data)
// navigator.clipboard.writeText(this.data)
this.$message.success('复制成功')
},
copyToClipboard(textToCopy) {
// navigator clipboard 需要https等安全上下文
if (navigator.clipboard && window.isSecureContext) {
// navigator clipboard 向剪贴板写文本
return navigator.clipboard.writeText(textToCopy);
} else {
// 创建text area
let textArea = document.createElement("textarea");
textArea.value = textToCopy;
// 使text area不在viewport,同时设置不可见
textArea.style.position = "absolute";
textArea.style.opacity = 0;
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return new Promise((res, rej) => {
// 执行复制命令并移除文本框
document.execCommand('copy') ? res() : rej();
textArea.remove();
});
}
}
}
}
</script>
<style lang="scss" scoped>
.copy{
.el-button{
padding: 1px 2px;
background: #dfdfdf;
}
}
</style>