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>