3.1 Browser – useClipboard
https://vueuse.org/core/useClipboard/
作用
响应式剪贴板API。提供响应剪贴板命令(剪切、复制和粘贴)以及异步读取和写入系统剪贴板的能力。对剪贴板内容的访问是在Permissions API后面进行控制的。未经用户许可,不得阅读或修改剪贴板内容。
官方示例
import { useClipboard } from '@vueuse/core'
const source = ref('Hello')
const { text, copy, copied, isSupported } = useClipboard({ source })
- text:剪贴板的内容
- copy:复制操作,也就是往剪贴板写入的操作
- copied:是否复制了内容,默认
copy
后为true
,一定时间后重新改为false
- isSupported:浏览器是否支持剪贴板。注意不能配置
legacy: true
,否则始终返回true
。 - 当浏览器不支持Clipboard API的时候,可以配置
legacy: true
,来使用execCommand
方式来实现复制的功能。
源码分析
一般的用法就以下几种:
- 调用
copy
复制文件 - 手动修改
text
,从而影响剪贴板的内容 - *如果增加
{read: true}
这个配置项,那么会在command+c
或者command+x
的时候,自动更新text的值。
export function useClipboard(options: UseClipboardOptions<MaybeComputedRef<string> | undefined> = {}): UseClipboardReturn<boolean> {
const {
navigator = defaultNavigator,
read = false, // 如果开启read,会在复制和剪切的时候,更新text的值
source,
copiedDuring = 1500, // 如果调用copy,copied会变成true,1.5s后重新变成false
legacy = false,
} = options
const events = ['copy', 'cut']
const isClipboardApiSupported = useSupported(() => (navigator && 'clipboard' in navigator))
const isSupported = computed(() => isClipboardApiSupported.value || legacy)
const text = ref('')
const copied = ref(false)
const timeout = useTimeoutFn(() => copied.value = false, copiedDuring)
function updateText() {
// 如果支持ClipboardApi,那么从剪贴板读取文字,赋值给text
if (isClipboardApiSupported.value) {
navigator!.clipboard.readText().then((value) => {
text.value = value
})
}
else {
// 如果不支持,那么使用传统方式读取
text.value = legacyRead()
}
}
// 如果read是true,那么监听'copy', 'cut'这两个事件,当事件触发,修改text
if (isSupported.value && read) {
for (const event of events)
useEventListener(event as WindowEventName, updateText)
}
/**
* 这是主要函数,只做了一件事,就是把传入的value写出剪贴板
*/
async function copy(value = resolveUnref(source)) {
if (isSupported.value && value != null) {
if (isClipboardApiSupported.value)
await navigator!.clipboard.writeText(value)
else
legacyCopy(value)
text.value = value
copied.value = true
// 定时是为了1.5s后再改回来
timeout.start()
}
}
function legacyCopy(value: string) {
const ta = document.createElement('textarea')
ta.value = value ?? ''
ta.style.position = 'absolute'
ta.style.opacity = '0'
document.body.appendChild(ta)
ta.select()
// execCommand 指的是执行命令,这里的copy的是选中的内容
// 因为是传入value的形式,所以用户实际上没有选中任何值,才创建了一个textarea并自动选中它
document.execCommand('copy')
ta.remove()
}
// 传统方式这里,直接返回 选中的文字
function legacyRead() {
return document?.getSelection?.()?.toString() ?? ''
}
return {
isSupported,
text: text as ComputedRef<string>,
copied: copied as ComputedRef<boolean>,
copy,
}
}