一、前端实现复制
1. document.execCommand(‘copy’)
已弃用: 不再推荐使用该特性。虽然一些浏览器仍然支持它,但也许已从相关的 web 标准中移除,也许正准备移除或出于兼容性而保留。请尽量不要使用该特性,并更新现有的代码。请注意,该特性随时可能无法正常工作。
这里是借用 input 或 textarea 来实现。
实现一个复制的方法
// src/hooks/useCopy.ts
import {ElMessage} from 'element-plus';
/**
* 实现文字复制
* @param copyValue 将要复制的文字
*/
export const useCopy = (copyValue: string) => {
// 创建输入框
let inputDom = document.createElement('input');
// 给输入框value赋值
inputDom.value = copyValue;
// 把input框添加到body上
document.body.appendChild(inputDom);
// 选中输入框中的内容
inputDom.select();
// 复制文字到剪切板
const hasCopy = document.execCommand('Copy');
ElMessage({
type: hasCopy ? 'success' : 'error',
message: hasCopy ? '复制成功' : '复制失败'
});
// 删除创建的dom节点
document.body.removeChild(inputDom);
}
引用复制方法
<template>
<div class="choose-icon">
<div>{{ value }}</div>
<el-button type="primary" @click="handleCopy">复制</el-button>
</div>
</template>
<script lang="ts" setup>
import { useCopy } from "@/hooks/useCopy";
let value = "11212fdgafaweaqwreqrqr";
let handleCopy = () => {
useCopy(value);
};
</script>
2. navigator.clipboard 实现复制文字
只有在用户事先授予网站或应用对剪切板的访问许可之后,才能使用异步剪切板读写方法。Chrome 浏览器规定,只有 HTTPS 协议的页面才能使用这个 API。不过,开发环境(
localhost
)允许使用非加密协议。
复制方法的实现
// src/hooks/useCopy.ts
import {ElMessage} from 'element-plus';
/**
* 实现文字复制
* @param copyValue 将要复制的文字
*/
export const useCopy = (copyValue: string) => {
try {
// 如果浏览器支持则会放回 Clipboard 对象,否则返回 undefined
const clipboard = navigator.clipboard;
if (clipboard) {
clipboard.writeText(copyValue).then(() => {
ElMessage({
type: 'success',
message: '复制成功'
});
});
} else {
ElMessage({
type: 'error',
message: '该浏览器不支持复制,请尝试换其它浏览器!'
});
}
} catch (error) {
console.log('error:', error);
}
};
引用复制方法
<template>
<div class="choose-icon">
<div>{{ value }}</div>
<el-button type="primary" @click="handleCopy">复制</el-button>
</div>
</template>
<script lang="ts" setup>
import { useCopy } from "@/hooks/useCopy";
let value = "11212fdgafaweaqwreqrqr";
let handleCopy = () => {
useCopy(value);
};
</script>
3. navigator.clipboard 实现复制图片
<template>
<div class="choose-icon">
<img :src="src" alt="" style="width: 100px; height: 100px" />
<el-button type="primary" @click="handleCopy">复制</el-button>
<div
id="image-container"
style="width: 100px; height: 100px; border: 1px solid red"
></div>
</div>
</template>
<script lang="ts">
import imgSrc from "@/assets/images/login_bg2.png";
export default {
setup() {
const src = imgSrc;
const handleCopy = () => {
let imgBlob;
fetch(src).then(async (res) => {
try {
// 图片转换成流
imgBlob = await res.blob();
// const text = new Blob(["cccccccccc"], { type: "text/plain" });
// 实现图片复制
const item = new ClipboardItem({ [imgBlob.type]: imgBlob });
await navigator.clipboard.write([item]);
console.log("文本复制成功");
// 实现图片读取(粘贴)
const clipboardContents = await navigator.clipboard.read();
clipboardContents.forEach(async (item: any) => {
const blob = await item.getType("image/png");
const imgDom = document.createElement("img");
imgDom.style.width = "100%";
imgDom.style.height = "100%";
imgDom.src = URL.createObjectURL(blob);
const divDom = document.getElementById("image-container");
divDom?.appendChild(imgDom);
});
} catch (error) {
console.log("error:", error);
}
});
};
return {
src,
handleCopy,
};
},
};
</script>
二、前端实现阻止用户复制文本
监听用户右键复制操作(可以整个系统复制监听,也可以对某段文字进行监听),当用户进行复制时,判断用户当前有无权限,只有有权限才可以复制,否则不可以并进行一系列操作。
实现
<template>
<div class="choose-icon">
<div>
身份:
<span style="color: red; font-weight: bold">{{ isVip ? "会员" : "普通用户" }}</span>
</div>
<div id="vip-text">{{ value }}</div>
<el-button
type="primary"
@click="
() => {
isVip = !isVip;
}
"
>
切换身份
</el-button>
</div>
</template>
<script lang="ts" setup>
import { useCopy } from "@/hooks/useCopy";
import { ElMessage } from "element-plus";
import { onMounted, ref } from "vue";
let value = "11212fdgafaweaqwreqrqr";
let isVip = ref(true);
onMounted(() => {
const textDom = document.getElementById("vip-text")!;
textDom.addEventListener("copy", (e) => {
e.preventDefault();
if (isVip.value) {
// 获取手表选中内容, 加 "" 是为了把获取的对象转字符串
const selectContent = window.getSelection() + "";
// 此处使用 navigator.clipboard 来实现文字的复制
useCopy(selectContent);
window.getSelection()?.empty();
} else {
ElMessage({
type: "error",
message: "请先升级为VIP会员",
});
}
});
});
</script>