跳转到内容

复制粘贴与内容设置

刀刀

1/8/2025

0 字

0 分钟

在平时开发或日常使用电脑时,经常都会需要复制一些内容。下面有三个场景:

  1. 复制一个图片,粘贴该图片。常见于富文本框
  2. 复制一段话,粘贴后失败或者被修改为版本信息。常见于一些付费文档网站
  3. 复制一段话,末尾跟随作者信息和网站信息。常见于掘金、知乎这类网站

这些功能都是使用同一套 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 属性,inputtextarea 是无法粘贴图片的。

然后监听该 divpaste 粘贴事件,通过 e.clipboardData.files 获取粘贴的内容。如果复制的内容是文字,则长度是0,复制的图片或文件长度大于0。

因此需要去判断遍历 e.clipboardData.files 数组是否大于0,大于0说明有文件,有文件就不能直接粘贴了,需要手动处理。

  1. 阻止默认行为
  2. 拿到第一项文件
  3. 读取该文件为 DataURL
  4. 创建 img 元素
  5. 赋值展示图片
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>

总体效果