web 如何实现点击复制功能

872 阅读2分钟

web 如何实现点击复制功能

在一些业务场景中,我们可能需要点击复制的功能,那我们如何去实现呢?

我们这里介绍几种比较常见的方法,这里使用 vite 脚手架创建的 vue 项目为 demo 实例。

document.execCommand

document.execCommand('copy') 是早期在 web 上实现复制功能的方法,现在已经被标记为废弃,但是在业务开发中还是会经常使用(个人感觉问题不大

兼容性

image.png

具体实现

function copyString(str: string) {
  const input = document.createElement("input");
  input.value = str;
  input.style.opacity = "0";
  document.body.appendChild(input);

  input.select();
  try {
    const code = document.execCommand("copy");
    if (code) {
      console.log("复制成功");
    } else {
      console.log("复制失败");
    }
  } catch (e) {
    console.log("复制失败");
  }
  document.body.removeChild(input);
}

步骤如下:

  • 创建一个 input 元素
  • 将要复制的值赋值给 input 的 value
  • 设置样式将其隐藏
  • 添加到 body 上
  • 调用 document.execCommand('copy') 方法复制
  • 移除节点

Clipboard

既然 document.execCommand('copy') 被废弃了,那么有没有什么替代方式呢?当然有,那就是 ClipboardAPI ,剪贴板 Clipboard API 提供了响应剪贴板命令(剪切、复制和粘贴)与异步读写系统剪贴板的能力。从权限 Permissions API 获取权限之后,才能访问剪贴板内容;如果用户没有授予权限,则不允许读取或更改剪贴板内容。该 API 被设计用来取代使用 document.execCommand() 的剪贴板访问方式。

兼容性

image.png

具体实现

async function copyStringByClipBoard(str: string) {
  try {
    await navigator.clipboard.writeText(str);
    console.log("复制成功");
  } catch (e) {
    console.log("复制失败");
  }
}

这个 clipboard 被放在 navigator 中,我们调用 clipboard 中的 writeText 方法去进行赋值,但是需要注意的是,这里这个方法返回的是一个 promise。

这个 ClipboardAPI 还是很强大的,除了可以复制文本,还可以复制别的一些东西,需要调用 write 方法,这里就不展开了,有兴趣的小伙伴可以去看一下 developer.mozilla.org/zh-CN/docs/…

clipboard.js

除了自己实现,我们还可以借助第三方库来帮助我们实现复制,那就是 clipboard.js

使用方法

安装

npm install clipboard --save

使用方法

// template
<div class="btn" data-clipboard-text="我是一个大帅哥">clipboard 点击复制</div>
  
// script
const clipboard = new ClipboardJS(".btn");
clipboard.on("success", function (e) {
  console.info("Action:", e.action);
  console.info("Text:", e.text);
  console.info("Trigger:", e.trigger);

  e.clearSelection();
});

clipboard.on("error", function (e) {
  console.error("Action:", e.action);
  console.error("Trigger:", e.trigger);
});

clipboardJs 这里利用了 h5 的数据属性,和 dom 进行强相关

原理

去看了一下clipboardjs,本质上用到的也是 document.execCommand ,这就是为什么我上面说个人觉得问题不大了......

github1s.com/zenorocha/c…

/**
 * Creates a fake textarea element with a value.
 * @param {String} value
 * @return {HTMLElement}
 */
export default function createFakeElement(value) {
  const isRTL = document.documentElement.getAttribute('dir') === 'rtl';
  const fakeElement = document.createElement('textarea');
  // Prevent zooming on iOS
  fakeElement.style.fontSize = '12pt';
  // Reset box model
  fakeElement.style.border = '0';
  fakeElement.style.padding = '0';
  fakeElement.style.margin = '0';
  // Move element out of screen horizontally
  fakeElement.style.position = 'absolute';
  fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px';
  // Move element to the same position vertically
  let yPosition = window.pageYOffset || document.documentElement.scrollTop;
  fakeElement.style.top = `${yPosition}px`;

  fakeElement.setAttribute('readonly', '');
  fakeElement.value = value;

  return fakeElement;
}

github1s.com/zenorocha/c…

/**
 * Executes a given operation type.
 * @param {String} type
 * @return {Boolean}
 */
export default function command(type) {
  try {
    return document.execCommand(type);
  } catch (err) {
    return false;
  }
}

总结

我们可以直接使用 clipboardjs 开源库去实现我们的点击复制功能,之后如果不兼容的话,我们更换库即可,现在压力给到了 clipboardjs