本文参考了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浏览器上进行测试,先记录下来,回头再测试下。
感谢阅读,如果有任何问题,希望大家指正。