ClipboardJS无效解决方案
需求场景:
列表需要复制链接功能,但是链接内容需动态生成,所以要在每次点击复制链接后请求后端接口,待请求响应后,复制返回内容。
基本实现:
async copyLink (event, id) {
try {
// 请求内容
const text = await getLinkApi(id)
const clipboard = new ClipboardJS(event.target, { text: () => text })
clipboard.on('success', e => {
this.$success('复制成功')
e.clearSelection()
clipboard.destroy()
})
clipboard.on('error', () => {
this.$message.error('复制失败')
clipboard.destroy()
})
clipboard.onClick(event)
} catch (e) {
this.$message.error(e)
}
}
发现问题:
但是在运行之后,却出现了 [Vue warn]: Error in v-on handler (Promise/async): "TypeError: Cannot read property 'hasAttribute' of null"
的错误
通过查看源码,发现hasAttribute
的调用发生在getAttributeValue
方法中
而getAttributeValue
方法的调用发生在defaultAction
不难发现,就是因为此时trigger
为空,导致获取节点属性方法报错。而trigger
获取发生在onClick
中
那么,应该就是e.currentTarget
未获取到当前节点。因为我们这里加入了异步请求,此时方法为异步方法,触发事件调用该方法,同步代码执行完成后,代表当前事件结束,浏览器会将event事件对象中currentTarget
重置为空。所以在请求完成后,我们传入onClick的event中已经不包含此属性了,所以导致了后面的问题。
解决方案:
我们可以在进入方法时,将currentTarget
保存下来,待请求结束之后,将currentTarget
手动塞入event对象中。通过源码发现,此库只使用了事件对象的currentTarget
属性,所以也可直接传入包含currentTarget
属性的对象。最终实现
async copyLink (event, id) {
const currentTarget = event.currentTarget
try {
// 请求内容
const text = await getLinkApi(id)
const clipboard = new ClipboardJS(event.target, { text: () => text })
clipboard.on('success', e => {
this.$success('复制成功')
e.clearSelection()
clipboard.destroy()
})
clipboard.on('error', () => {
this.$message.error('复制失败')
clipboard.destroy()
})
clipboard.onClick({ currentTarget })
} catch (e) {
this.$message.error(e)
}
}