vue-复制

1,749 阅读3分钟

一、vue2

1. vue-clipboard2

  • 安装
npm install --save vue-clipboard2
  • 配置
import Vue from "vue"
import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard)
  • 使用一:点击元素触发
<button type="button"
   v-clipboard:copy="`copy`"
   v-clipboard:success="copySuccess"
   v-clipboard:error="copyError">copy</button>

methods: {
   copySuccess() {
     console.log("success");
   },
   copyError() {
     console.log("error");
   }
}
  • 使用二:方法中复制
<button @click="copyData">copy</button>
methods: {
    copyData() {
      // 如果不需要回调
      // this.$copyText("copy text");
      // 如果需要回调:
      this.$copyText("copy text").then(
        (e) => {
          alert("复制成功");
          console.log(e);
        },(e) =>{
          alert("复制失败");
          console.log(e);
        }
      );
    }
}

2. 自定义指令

  • 创建指令目录文件
    • 在项目的 src 目录下创建一个 directive 文件夹用来存放所有的指令代码文件
    • 创建 index.js 文件,用来管理所有的指令文件
    // ------ src/directive/index.js ------
    import copy from "./v-copy";
    
    // 自定义指令
    const directives = {
      copy,
    };
    
    export default {
      // 全局注册多文件指令
      install(Vue) {
        Object.keys(directives).forEach((key) => {
          Vue.directive(key, directives[key]);
        });
      },
    };
    
  • 在main.js中全局引入指令
import Directive from "@/directive/index.js"; // 自定义指令
Vue.use(Directive);
  • 开始创建指令
// ------ src/directive/v-copy.js ------
/**
 * 指令的钩子函数:
 * vue2指令文档:https://v2.cn.vuejs.org/v2/guide/custom-directive.html
 *
 * bind: 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
 * inserted: 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
 * update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
 * componentUpdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
 * unbind: 只调用一次,指令与元素解绑时调用。
 */
/**
 * 复制指令:v-copy
 * 用法:<button v-copy="`这是你要复制的文本`">copyText</button>
 */

// vant 的提示api(可替换成你们的)
// import { Toast } from "vant";

const copy = {
  /**
   * 指令绑定在DOM时调用,只执行一次
   * @param {*} el 指令所绑定的元素,可以用来直接操作 DOM
   * @param {*} binding 指令的信息,里面的value为指令绑定的值
   */
  bind(el, binding) {
    el.$value = binding.value;

    // 创建事件-复制文本逻辑
    el.copyFun = () => {
      if (!el.$value) {
        // Toast("暂无复制内容");
        console.log("暂无复制内容");
        return;
      }

      const textarea = document.createElement("textarea"); // 手动创建 textarea 文本标签
      textarea.value = el.$value; // 设置要复制的值

      document.body.appendChild(textarea); // 将 textarea 标签添加到页面中
      textarea.select(); // 选中文本框的值

      try {
        const result = document.execCommand("Copy"); // 复制
        if (result) {
          // Toast("复制成功"); // 复制成功
          console.log("复制成功");
        } else {
          // Toast("复制失败"); // 复制失败
          console.log("复制失败");
        }
      } catch {
        // 浏览器不支持
        // Toast("复制失败,请检查浏览器是否兼容");
        console.log("复制失败,请检查浏览器是否兼容");
      }

      document.body.removeChild(textarea); // 移除 textarea 标签
    };

    el.addEventListener("click", el.copyFun); // 绑定点击事件
  },

  /* 组件数据更新之后值行 */
  componentUpdated(el, binding) {
    el.$value = binding.value;
  },

  /* 与元素解绑时执行 */
  unbind(el) {
    // console.log("coyp-unbind:", el);
    el.removeEventListener("click", el.copyFun);
  },
};

export default copy;
  • 使用自定义指令
<button v-copy="`这是你要复制的文本`">v-copy</button>

二、vue3

1. vue-clipboard3

  • 安装
npm install --save vue-clipboard3
  • 使用
<template>
  <button @click="copy">copy</button>
</template>

<script setup>
// 导入插件
import useClipboard from 'vue-clipboard3'

// 使用插件
const { toClipboard } = useClipboard()
//点击复制
const copy = async () => {
  try {
    // 复制
    await toClipboard("copy")
    // 复制成功
    console.log("success")
  } catch (e) {
    // 复制失败
    console.log("error", e)
  }
}
</script>

2. 自定义指令

  • 创建指令目录文件
    • 在项目的 src 目录下创建一个 directive 文件夹用来存放所有的指令代码文件
    • 创建 index.js 文件,用来管理所有的指令文件
    // ------ src/directive/index.js ------
    import copy from "./v-copy";
    
    // 自定义指令
    const directives = {
      copy,
    };
    
    export default {
      // 全局注册多文件指令
      install(Vue) {
        Object.keys(directives).forEach((key) => {
          Vue.directive(key, directives[key]);
        });
      },
    };
    
  • 在main.js中全局引入指令
import Directive from "@/directive/index.js"; // 自定义指令
Vue.use(Directive);
  • 开始创建指令
// 原生copy方法
import { ElMessage } from "element-plus";
const copyText = (text) => {
  const textarea = document.createElement("textarea");
  textarea.value = text;
  document.body.appendChild(textarea);
  textarea.select();
  const successful = document.execCommand("copy");
  if (successful) {
    ElMessage.success("复制成功");
  } else {
    ElMessage.error("复制失败");
  }
  document.body.removeChild(textarea);
  return successful;
};
const copy = {
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding) {
    el.addEventListener("click", () => {
      if (binding.value) {
        const text =
          typeof binding.value === "string"
            ? binding.value
            : binding.value.text;
        copyText(text);
      }
    });
  },
};
export default copy;
// vue-clipboard3复制方法
import { ElMessage } from "element-plus";
import useClipboard from "vue-clipboard3";
 
const copyText = (text) => {
  const { toClipboard } = useClipboard();
  return new Promise((resolve, reject) => {
    try {
      toClipboard(text);
      ElMessage.success("复制成功");
      resolve(text);
    } catch (e) {
      ElMessage.error("复制失败");
      reject(e);
    }
  });
};
const copy = {
  mounted(el, binding) {
    el.addEventListener("click", () => {
      if (binding.value) {
        const text =
          typeof binding.value === "string"
            ? binding.value
            : binding.value.text;
        copyText(text);
      }
    });
  },
};
export default copy;
  • 使用自定义指令
<el-button v-copy="`这是你要复制的文本`">copyText</el-button>