复制粘贴与内容设置
作者:Yuan Tang
更新于:9 个月前
字数统计:697 字
阅读时长:2 分钟
在平时开发或日常使用电脑时,经常都会需要复制一些内容。下面有三个场景:
- 复制一个图片,粘贴该图片。常见于富文本框
- 复制一段话,粘贴后失败或者被修改为版本信息。常见于一些付费文档网站
- 复制一段话,末尾跟随作者信息和网站信息。常见于掘金、知乎这类网站
这些功能都是使用同一套 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', (e) => {
e.preventDefault()
})写入自定义内容
使用 navigator.clipboard.writeText() 方法,传入一个字符串,字符串的内容为需要写入的内容。
js
document.addEventListener('copy', (e) => {
e.preventDefault()
navigator.clipboard.writeText('自定义内容')
})复制一段话后面加内容
在 copy 事件中,通过 e.target.innerHTML 获取复制的内容,在后面拼接新的内容,再将内容作为参数传给 navigator.clipboard.writeText() 方法。
js
document.addEventListener('copy', (e) => {
console.log('e', e.target.innerHTML, navigator)
navigator.clipboard.writeText(`${e.target.innerHTML}来源:tydumpling博客<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 />
</template>