• 作者:老汪软件技巧
  • 发表时间:2024-11-30 17:03
  • 浏览量:

本文旨在记录解决在工作中一键复制功能得需求,使用Vue3+TypeScript+Ant-Design-Vue

什么是vue自定义指令?请移步

实现的指令兼容了不支持navigator.clipboard API的浏览器,且实现了节流的效果,默认间隔时间1000ms

1、创建一个文件,比如:copy.ts

import { notification } from 'ant-design-vue'
// 自定义一些属性
interface IListenter {
  (event: MouseEvent): void
}
interface ICopyElement extends HTMLElement {
  $value: string
  $isSupported: boolean
  $isClick: boolean
  $timer: number
  $handleCopy: IListenter
}
const useCopy = (app: ReturnType<typeof createApp>) => {
  app.directive('copy', {
    mounted(el: ICopyElement, binding: ReturnType<typeof Object>) {
      console.log(binding)
      let timer = binding.arg?.split(':')[0] || ''
      // 判断timer是否存在,且是否为数字,如果不是数字则赋值默认值 1000ms
      if (timer && parseInt(timer) != timer) {
        el.$timer = parseInt(timer)
      } else {
        el.$timer = 1000
      }
      el.$value = binding.value
      el.$handleCopy = async (event: MouseEvent) => {
        // 简单做个节流
        if (el.$isClick) return
        el.$isClick = true
        let t = setTimeout(() => {
          clearTimeout(t)
          el.$isClick = false
        }, el.$timer)
        if (!el.$value) {
          // 值为空的时候,给出提示
          notification.warning({ message: '系统提示', description: '无复制内容' })
          return
        }
        // 获取是否支持复制api
        if (el.$isSupported === undefined) {
          el.$isSupported = navigator && 'clipboard' in navigator
        }
        // 判断浏览器是否支持 navigator.clipboard
        if (!el.$isSupported) {
          // 不支持,使用旧的复制方式
          // 动态创建 textarea 标签
          const textarea = document.createElement('textarea')
          // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
          textarea.readOnly = true
          textarea.style.position = 'fixed'
          textarea.style.left = '-9999px'
          // 将要 copy 的值赋给 textarea 标签的 value 属性
          textarea.value = el.$value
          // 将 textarea 插入到 body 中

_复制指令是指什么_一键复制按钮代码

document.body.appendChild(textarea) // 选中值并复制 textarea.select() // textarea.setSelectionRange(0, textarea.value.length); const result = document.execCommand('Copy') if (result) { notification.success({ message: '系统提示', description: '复制成功' }) } document.body.removeChild(textarea) } else { // 使用 clipboard API await navigator!.clipboard.writeText(el.$value) notification.success({ message: '系统提示', description: '复制成功' }) } } el.addEventListener('click', el.$handleCopy, false) }, unmounted(el: ICopyElement) { el.removeEventListener('click', el.$handleCopy) } }) } export default (app: ReturnType<typeof createApp>) => { useCopy(app) }

2、在main.ts文件中使用

import App from './App.vue'
import * as copyFn from './copy' // 上面创建的文件
const app = createApp(App)
if (typeof copyFn.default === 'function') {
    copyFn.default(app)
}
app.mount('#app')

上面的写法可以根据自己项目中的情况改变

3、使用

// test.vue


总结

总的来说这个自定义指令比较简单,实现这个指令是为了项目中多处地方方便使用,此文章不过多的解释其中的代码,有需要的可以直接复制到自己代码中测试一下。