/** * v-copy 指令 - 点击自动复制文本 * * 用法: * ... * {{ userId }} */ import type { Directive, DirectiveBinding, VNode } from 'vue'; /** * 将文本复制到系统剪贴板,并显示成功提示。 * * @param data 待复制的字符串 */ function copyText(data: string) { uni.setClipboardData({ data, showToast: false, // 禁用系统默认 Toast 提示,使用自定义的无图标 Toast success: () => uni.showToast({ title: '复制成功', icon: 'none', duration: 1500 }), }); } /** * 向虚拟节点 (VNode) 的 props 中注入 onTap 事件。 * 当用户点击该组件时,执行原有的点击事件后自动触发复制绑定值。 * * @param vnode 虚拟 DOM 节点 * @param binding 指令绑定对象 */ function injectTap(vnode: VNode, binding: DirectiveBinding) { if (!vnode.props) (vnode as any).props = {}; const props = vnode.props as Record; const prev = props.onTap; props.onTap = (e: any) => { prev?.(e); const value = binding.value; if (value == null || value === '') return; copyText(String(value)); }; } /** * 自定义 Vue 指令 `v-copy` * * 在元素/组件被创建或更新前,拦截其点击事件并注入复制剪贴板逻辑。 */ export const vCopy: Directive = { /** * 在指令创建时注入点击事件拦截器。 */ created(el: any, binding: DirectiveBinding, vnode: VNode) { injectTap(vnode, binding); }, /** * 在绑定值更新前重新注入点击事件拦截器,以获取最新的绑定值。 */ beforeUpdate(el: any, binding: DirectiveBinding, vnode: VNode) { injectTap(vnode, binding); }, };