复制粘贴与内容设置
刀刀
1/8/2025
0 字
0 分钟
在平时开发或日常使用电脑时,经常都会需要复制一些内容。下面有三个场景:
- 复制一个图片,粘贴该图片。常见于富文本框
- 复制一段话,粘贴后失败或者被修改为版本信息。常见于一些付费文档网站
- 复制一段话,末尾跟随作者信息和网站信息。常见于掘金、知乎这类网站
这些功能都是使用同一套 API 来完成的,这个 API 就是 Clipboard API。该 API 包含两点:
- 对象,指
navigator.clipboard
,可用于写入和读取剪切板 - 事件,有两个事件:
navigator.clipboard.oncopy
:可以监听视窗以内的复制,如 ctrl + c 和 鼠标右键复制navigator.clipboard.oncut
:可以监听视窗以内的剪切,如 ctrl + x 和 鼠标右键剪切navigator.clipboard.onpaste
:可以监听视窗以内的粘贴,如 ctrl + v 和 鼠标右键粘贴
下面来依次实现上述的操作。
不允许复制并写入自定义内容
不允许复制
为 document
绑定 copy
事件,触发 copy
事件后通过 e.preventDefault()
阻止默认行为。
js
document.addEventListener('copy', function (e) {
e.preventDefault()
})
写入自定义内容
使用 navigator.clipboard.writeText()
方法,传入一个字符串,字符串的内容为需要写入的内容。
js
document.addEventListener('copy', function (e) {
e.preventDefault()
navigator.clipboard.writeText('自定义内容')
})
复制一段话后面加内容
在 copy
事件中,通过 e.target.innerHTML
获取复制的内容,在后面拼接新的内容,再将内容作为参数传给 navigator.clipboard.writeText()
方法。
js
document.addEventListener('copy', function (e) {
console.log('e', e.target.innerHTML, navigator);
navigator.clipboard.writeText(e.target.innerHTML + `来源:刀刀博客<br/>每天都要更努力`)
})
刷新后粘贴剪切板内容
通过 navigator.clipboard.readText()
方法读取剪切板的内容,并将其赋值给 document.body.innerHTML
。该方法返回的是一个 Promise
对象,所以需要使用 .then()
方法来获取读取到的内容。
js
navigator.clipboard.readText().then((text) => {
document.body.innerHTML = text
})
粘贴文件
粘贴图片需要在富文本框中实现,先给一个 div
添加 contenteditable
属性,input
和 textarea
是无法粘贴图片的。
然后监听该 div
的 paste
粘贴事件,通过 e.clipboardData.files
获取粘贴的内容。如果复制的内容是文字,则长度是0,复制的图片或文件长度大于0。
因此需要去判断遍历 e.clipboardData.files
数组是否大于0,大于0说明有文件,有文件就不能直接粘贴了,需要手动处理。
- 阻止默认行为
- 拿到第一项文件
- 读取该文件为
DataURL
- 创建
img
元素 - 赋值展示图片
vue
<script setup>
// 监听粘贴事件
onMounted(() => {
contentRef.value.addEventListener('paste', (e) => {
if(e.clipboardData.files.length > 0) {
e.preventDefault();
const file = e.clipboardData.files[0];
const reader = new FileReader();
reader.onload = function (e) {
const data = e.target.result;
const img = document.createElement('img');
img.src = data;
contentRef.value.appendChild(img)
}
reader.readAsDataURL(file);
}
})
})
</script>
<template>
<div ref="contentRef" contenteditable></div>
</template>