vue3自定义指令来实现 v-copy 功能

v-copy

在 Vue 3 中,可以通过自定义指令来实现 v-copy 功能

  • 定义指令 - 新建copy.ts文件
ts 复制代码
//安装
pnpm i lement-plus -D

import type { Directive, DirectiveBinding, App } from 'vue'
import { ElMessage } from 'element-plus' // 引入element-plus 插件
import { EventType } from '../types' //导入事件的类型

// 添加事件监听器函数
function addEventListener(el: Element, binding: DirectiveBinding) {
  const { value, arg, modifiers } = binding // 解构出绑定值、参数和修饰符
  console.log(value, modifiers, arg, 'ssss'); // 打印调试信息

  // 确定事件类型和提示消息
  const eventType: EventType = modifiers.dblclick ? 'dblclick' : 'click' // 根据修饰符确定事件类型
  const message = arg || '复制成功' as string // 使用指令参数作为提示消息,默认为"复制成功"
  el.setAttribute('copyValue', String(value)) // 将绑定值存储为元素属性

  // 复制操作的处理函数
  const copyHandler = async (): Promise<void> => {
    try {
      if (navigator.clipboard) {
        // 使用现代浏览器的剪贴板 API
        await navigator.clipboard.writeText(el.getAttribute('copyValue') || '')
      } else {
        // 使用兼容旧浏览器的方法
        legacyCopy(el.getAttribute('copyValue') || '')
      }
      // 如果没有启用静默模式,显示成功提示
      if (!modifiers.quiet) {
        ElMessage({
          message: message,
          type: 'success',
        })
      }
    } catch (err) {
      // 复制失败时显示错误提示
      ElMessage.error('复制失败!')
    }
  }

  // 为元素添加事件监听器
  el.addEventListener(eventType, copyHandler)
}

// 兼容旧浏览器的复制方法
function legacyCopy(textToCopy: string) {
  // 创建一个隐藏的 textarea 元素
  const textarea = document.createElement('textarea')
  textarea.value = textToCopy // 设置要复制的文本
  textarea.style.position = 'fixed' // 使其不可见
  document.body.appendChild(textarea) // 添加到文档中
  textarea.select() // 选中其内容
  // 使用 execCommand 执行复制操作
  if (!document.execCommand('copy')) {
    throw new Error('execCommand 执行失败') // 复制失败时抛出错误
  }
  document.body.removeChild(textarea) // 移除临时创建的 textarea
}

// 自定义指令定义
const vCopy: Directive = {
  // 元素挂载时执行
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    addEventListener(el, binding) // 添加事件监听器
  },
  // 元素更新时执行
  updated(el: HTMLElement, binding: DirectiveBinding) {
    const { value } = binding
    el.setAttribute('copyValue', String(value)) // 更新存储的文本值
  },
}

// 注册指令的函数
export const setupCopyDirective = (app: App<Element>) => {
  app.directive('copy', vCopy) // 注册自定义指令
}
export default vCopy // 默认导出指令
  • 事件类型导出types.ts

    export type EventType = 'click' | 'dblclick'

  • 在组件中,使用 v-copy 指令绑定需要复制的文本 directive.vue

vue 复制代码
<script setup lang="ts">
  import {ref} from "vue";
  import { BaseButton } from '@/components/Button'
  import { ElInput } from 'element-plus'
  const value = ref<string>('我是要复制的值')
  const change = ref<string>('我是要改变的值')
</script>

<template>
  <button v-copy.dblclick="value">点击我复制</button>
  <BaseButton type="primary" class="w-[20%]" v-copy:复制成功了.dblclick="value">
    点击我复制
  </BaseButton>
  <el-input v-model="change" placeholder="Please input" />
  <BaseButton type="primary" class="w-[20%]" @click="() => value = change">
    改变将要复制的值
  </BaseButton>

</template>
相关推荐
发现一只大呆瓜6 分钟前
Vue - @ 事件指南:原生 / 内置 / 自定义事件全解析
前端·vue.js·面试
庄小焱15 分钟前
React——React基础语法(1)
前端·javascript·vue.js
pingan878739 分钟前
试试 docx.js 一键生成 Word 文档,效果很不错
开发语言·前端·javascript·ecmascript·word
张一凡931 小时前
重新理解 React 状态管理:用类的方式思考业务
前端·react.js
结网的兔子2 小时前
前端学习笔记——Element Plus 栅格布局系统示例
前端·javascript·css
l1t2 小时前
DeepSeek总结的用 C# 构建 DuckDB 插件说明
前端·数据库·c#·插件·duckdb
zhensherlock2 小时前
Protocol Launcher 系列:App Store 精准引流与应用推广
javascript·macos·ios·typescript·iphone·mac·ipad
泯泷2 小时前
从零构建寄存器式 JSVMP:实战教程导读
前端·javascript·算法
椰子皮啊2 小时前
mediasoup+Vue3避坑指南:解决黑屏、闪屏、流绑定失效三大难题
vue.js·前端框架
叫我一声阿雷吧2 小时前
JS 入门通关手册(24):Promise:从回调地狱到异步优雅写法
javascript·前端开发·promise·前端面试·异步编程·js进阶·js异步