vue3中将插件 Clipboard.js封装为指令,支持异步请求复制

639 阅读2分钟

本文参考了vue中将插件 Clipboard.js封装为指令这篇文章的观点,在此基础上实现了异步请求复制的功能。

之前在项目中遇到一个需求:点击复制内容。本来用 vue-clipboard3 插件很方便就能实现,但是我们需要复制的是前端请求返回的数据,safari浏览器上会存在响应问题。

最近在看自定义指令的实现,掘金上也有不少的帖子,但是好多是基于textArea的execCommand属性去copy值,但是execCommand属性已经废弃了,感觉是个坑,所以想用clipboard封装下指令并且支持异步请求。

普通使用方式:
<button v-copy="'普通复制'">普通复制</button>
异步请求使用方式:
<button v-copy:async="'异步请求复制'">异步请求复制</button>
// main.js 
import { createApp } from 'vue' 
import App from './App.vue' 
import { router } from './router' 
// 引入自定义指令-copy为例
import copy from './directive/copy.js'

const app = createApp(App) 
app.use(router)
app.directive('copy', copy)
app.mount('#app')
// ./directive/copy.js
import Clipboard from 'clipboard';

// clipboard逻辑
function copyText(el) {
    const clipboard = new Clipboard(el);
    clipboard.on('success', function () {
        console.log('复制成功')
        clipboard.destroy();
    });
    clipboard.on('error', function () {
        console.log('复制失败')
    });
}

// 元素绑定逻辑
function bindCopy(el, binding) {
    // 配置 Clipboard 属性
    el.setAttribute('data-clipboard-text', binding.value)
    // 解决第一次复制无法成功问题
    el.onmouseenter = () => copyText(el)
    // 进行复制
    el.onclick = () => copyText(el)
}

const copy = {
    mounted(el, binding) {
        bindCopy(el, binding)
    },
    updated(el, binding) {
        // 实时更新最新的目标内容;主要用来监听指令绑定的元素变化数据
        if (binding.arg === 'async') {
            bindCopy(el, binding)
        }
    },
}

export default copy;

可以写个promise测试下

<script setup lang="ts">
import { ref } from 'vue';

const copyValue = ref('')

const asyncData = new Promise((resolve, reject) => {
  resolve('这是异步数据')
})

asyncData.then(res => {
  copyValue.value = String(res)
})
</script>

<template>
    普通使用方式:
    <button v-copy="'普通复制'">普通复制</button>
    异步请求使用方式:
    <button v-copy:async="copyValue">异步请求复制</button>
</template>

之前遇到这个问题是将异步请求修改成ajax同步请求,在拿到返回值后新建Clipboard对象赋值,手头暂时不方便在safari浏览器上进行测试,先记录下来,回头再测试下。

感谢阅读,如果有任何问题,希望大家指正。