复制文本指令(v-copy)

484 阅读2分钟

核心思想

复制文本指令的核心就是 拿到当前想要复制的文本内容,放在一个input输入框中,通过input元素的select属性选中文本内容,然后通过document.execCommand('copy')实现文本复制。

  • 实现代码
    function handleClick(text: string) {
      // 创建元素
      if (!document.getElementById("copyTarget")) {
        const copyTarget = document.createElement("input");
        copyTarget.setAttribute(
          "style",
          "position:fixed;top:0;left:0;opacity:0;z-index:-1000;"
        );
        copyTarget.setAttribute("id", "copyTarget");
        document.body.appendChild(copyTarget);
      }
    
      // 复制内容
      const input: any = document.getElementById("copyTarget");
      input.value = text;
      input.select();
      document.execCommand("copy");
      ElMessage({
        message: "复制成功!",
        grouping: true,
        type: "success",
      });
    }
    

document.execCommand

虽然一些浏览器仍然支持它,但也许已从相关的 web 标准中移除,也许正准备移除或出于兼容性而保留,不推荐使用。

  • 语法
    /**
    * aCommandName 命令的名称
    * aShowDefaultUI 是否展示用户页面,默认false
    * aValueArgument 一些命令(例如 insertImage)需要额外的参数(insertImage 需要提供插入 image 的 url),默认为 null。
    * bool:返回值为Boolean类型,如果是 `false` 则表示操作不被支持或未被启用。
    **/
     bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
    
  • aCommandName
    • copy 拷贝当前选中内容到剪贴板。
    • cut 剪贴当前选中的文字并复制到剪贴板。
    • paste 在光标位置粘贴剪贴板的内容
    • ....查看更多

单击复制文本(v-copy)

  • 添加单击事件
    const copy: Directive = {
      mounted(el: any, binding: DirectiveBinding) {
          el.addEventListener("click", () => handleClick(el.innerText));
          el.style.cursor = "copy";
      },
    }
    

双击复制文本(v-copy.dblclick)

  • 区分单击指令,给指令追加修饰符dblclick
  • 添加监听事件dblclick
    const copy: Directive = {
      mounted(el: any, binding: DirectiveBinding) {
           if (binding.modifiers.dblclick) {
              el.addEventListener("dblclick", () => handleClick(el.innerText));
              el.style.cursor = "copy";
            }
      },
    }
    

点击图标复制文本(v-copy.icon)

  • 区分指令,给指令追加修饰符icon
  • 这里实现的思想是,给要复制文本的元素追加子元素(图标元素),点击的时候判断父元素中是否包含图标元素,包含则为其添加监听事件
    const copy: Directive = {
      mounted(el: any, binding: DirectiveBinding) {
           if (binding.modifiers.dblclick) {
              el.addEventListener("dblclick", () => handleClick(el.innerText));
              el.style.cursor = "copy";
            }
      },
    }
    

完整指令

/**
 * v-copy
 * 点击复制指令,可自行扩展至input
 * 接收参数:function类型
 */
import type { Directive, DirectiveBinding } from "vue";
import { ElMessage } from "element-plus";
function handleClick(text: string) {
  // 创建元素
  if (!document.getElementById("copyTarget")) {
    const copyTarget = document.createElement("input");
    copyTarget.setAttribute(
      "style",
      "position:fixed;top:0;left:0;opacity:0;z-index:-1000;"
    );
    copyTarget.setAttribute("id", "copyTarget");
    document.body.appendChild(copyTarget);
  }

  // 复制内容
  const input: any = document.getElementById("copyTarget");
  input.value = text;
  input.select();
  document.execCommand("copy");
  ElMessage({
    message: "复制成功!",
    grouping: true,
    type: "success",
  });
}
const copy: Directive = {
  mounted(el: any, binding: DirectiveBinding) {
    // 双击触发复制
    if (binding.modifiers.dblclick) {
      el.addEventListener("dblclick", () => handleClick(el.innerText));
      el.style.cursor = "copy";
    }
    // 点击icon触发复制
    else if (binding.modifiers.icon) {
      if (el.hasIcon) return;
      const iconElement = document.createElement("i");
      iconElement.setAttribute(
        "class",
        "iconfont icon-sishuxiangqing-huodongxiangqing"
      );
      iconElement.setAttribute("style", "margin-left:5px");
      el.appendChild(iconElement);
      el.hasIcon = true;
      iconElement.addEventListener("click", () => handleClick(el.innerText));
      iconElement.style.cursor = "copy";
    }
    // 单击触发复制
    else {
      el.addEventListener("click", () => handleClick(el.innerText));
      el.style.cursor = "copy";
    }
  },
};

export default copy;