大家好,我是若川。持续组织了近一年的源码共读活动,感兴趣的可以 点此加我微信ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外:目前建有江西|湖南|湖北籍前端群,可加我微信进群。

本文来自读者@NewName 的投稿。(基本我出一期源码共读就写一篇笔记的小伙伴),他自己曾说学到很多,同时更热爱学习了。


日常开发中我们有时会遇到拷贝粘贴的功能,笔者还记得曾经使用过react-copy-to-clipboard 和 vue-clipboard2。最近在看vueuse的时候发现了useClipboard就简单研究了一下,日后vue3项目中如果有使用场景可以用一下。

1.原生Clipboard

在看useClipboard源码之前,需要一些前置知识,那就是原生Clipboard的API。首先通过一张图概览一下浏览器原生Clipboard的相关知识:对上图涉及的知识逐一解释:

  • 剪贴板 Clipboard API 提供了响应剪贴板命令与异步读写系统剪贴板的能力。

  • 从权限 Permissions API 获取权限之后,才能访问剪贴板内容。

  • Clipboard API 包括异步剪贴板 API(AsyncClipboard API)和 剪贴板事件 API(Clipboard Event API)。

  • Clipboard读取剪切板有两个方法read()和readText()分别用于读取数据(比如图片)和文本;写入剪切板有两个方法write()和writeText()分别用于将任意数据写入和将文本写入。

  • ClipboardEvent接口描述了与修改剪切板相关信息的事件,包括剪切,复制和粘贴。

更多关于Clipboard API的细节以及兼容性问题您可以访问MDN文档详细学习。看一段示例代码:

navigator.clipboard.readText().then(clipText => document.querySelector(".editor").innerText += clipText);

2.useClipboard

2.1简介

useClipboard是响应式的剪贴板 API。提供剪贴板命令(剪切、复制和粘贴)以及异步读取和写入系统剪贴板的能力。访问剪贴板内容需要获得Permission API的相关权限,未经用户许可则不允许读取或更改剪贴板内容。

2.2例子

官方文档的示例代码如下所示:

<script setup lang="ts">
import { ref } from 'vue'
import { useClipboard, usePermission } from '@vueuse/core'const input = ref('')const { text, isSupported, copy } = useClipboard()
const permissionRead = usePermission('clipboard-read')
const permissionWrite = usePermission('clipboard-write')
</script><template><div v-if="isSupported"><note>Clipboard Permission: read <b>{{ permissionRead }}</b> | write<b>{{ permissionWrite }}</b></note><p>Current copied: <code>{{ text || 'none' }}</code></p><input v-model="input" type="text"><button @click="copy(input)">Copy</button></div><p v-else>Your browser does not support Clipboard API</p>
</template>

首先引入 useClipboard,从useClipboard中解构出text, isSupported, copy。text是当前从剪切板读取到的文本,isSupported用于判断当前浏览器是否支持剪切板API,copy是将文本写入到剪切板的方法。usePermission用于获取权限,使用其查看了clipboard-read和clipboard-write的权限,并将权限展示到页面上。通过下图可以看到读取的权限是prompt也就是询问,而写入操作被授权了即granted。定义了响应式的变量input绑定到input标签上,当用户点击按钮时则调用copy()方法将input的内容写入剪切板。初始时我们没有向剪切板写入内容,text是空字符串,所以页面显示当前拷贝内容为none:当用户输入'123'点击copy按钮后,text的值也就是从剪切板读取到的文本变成了'123',所以页面展示内容也变成了'123'

2.3源码

这里我们只保留了核心逻辑的40多行代码,您可以查看源码 浏览全部代码。

export function useClipboard(options: ClipboardOptions<MaybeRef<string> | undefined> = {}): ClipboardReturn<boolean> {const {navigator = defaultNavigator,read = false,source,copiedDuring = 1500,} = optionsconst events = ['copy', 'cut']const isSupported = Boolean(navigator && 'clipboard' in navigator)const text = ref('') // 与剪切板内容相对应的响应式值const copied = ref(false) // 是否拷贝完成const timeout = useTimeoutFn(() => copied.value = false, copiedDuring)// 更新textfunction updateText() {navigator!.clipboard.readText().then((value) => {text.value = value})}// 监听拷贝和剪切事件if (isSupported && read) {for (const event of events)useEventListener(event as WindowEventName, updateText)}// 将响应式值value拷贝到textasync function copy(value = unref(source)) {if (isSupported && value != null) {await navigator!.clipboard.writeText(value)text.value = valuecopied.value = truetimeout.start()}}return {isSupported,text: text as ComputedRef<string>,copied: copied as ComputedRef<boolean>,copy,}
}

2.3.1参数

(1)navigator默认为window.navigator, 其定义如下:

export const defaultNavigator = /* #__PURE__ */ isClient ? window.navigator : undefined

(2)read表示是否允许读取剪切板的内容,默认值是false, 也就是默认不实时读取剪切板的内容。我们通过例子的截图知道默认clipboard-read的值是prompt即询问,您可以通过浏览器的隐私设置来设置对于剪切板的权限:当调用useClipboard时指定了read为true, 并且你允许查看复制到剪切板中的数据,则此时只要剪切板里有内容就会实时显示:

const { text, isSupported, copy } = useClipboard({read:true})

上图是选中了"Clipboard"这几个字后右键点击复制后系统弹出确认框。上图是点击“允许”后复制到剪切板的内容实时赋值给了text并显示在页面中了。(3)source拷贝的源数据,可选的。source的原始值可以作为copy函数的默认值:

async function copy(value = unref(source)) {//省略}

如下图所示当没有指定source时的情况:可以看到value对应传给copy的参数input, 而source是undefined。(4)copiedDuring为重置copied的毫秒数,copied用来表示是否拷贝完成。

2.3.2updateText

function updateText() {navigator!.clipboard.readText().then((value) => {text.value = value})
}

updateText用于更新text的值,从剪切板中读取数据然后更新text,读取剪切板数据使用的是readText()方法。

2.3.3监听拷贝和剪切

if (isSupported && read) {for (const event of events)useEventListener(event as WindowEventName, updateText)
}

在允许读取剪切板的情况下,如果发生拷贝和剪切则用剪切板中的内容更新text。

2.3.4 copy方法

async function copy(value = unref(source)) {if (isSupported && value != null) {await navigator!.clipboard.writeText(value)text.value = valuecopied.value = truetimeout.start()}
}

copy方法用于将参数value写入剪切板并赋值给text,写入剪切板使用的是writeText()方法。至此,useClipbord的源码就分析完了,挺简单的但是读完也有收获。

3.总结

本文介绍了原生的Clipboard API之后又介绍了useClipboard 的使用,然后结合示例代码的调试过程分析了useClipboard 的源码。Clipboard API中的readText()和 writeText()是useClipboard 的灵魂。

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经坚持写了8年,点击查看年度总结。
同时,最近组织了源码共读活动,帮助4000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

扫码加我微信 ruochuan12、拉你进源码共读

今日话题

目前建有江西|湖南|湖北 籍 前端群,想进群的可以加我微信 ruochuan12 进群。分享、收藏、点赞、在看我的文章就是对我最大的支持

当CV工程师碰到了拷贝粘贴的需求——useClipboard的使用及源码解析相关推荐

  1. js define函数_不夸张,这真的是前端圈宝藏书!360前端工程师Vue.js源码解析

    优秀源代码背后的思想是永恒的.普适的. 这些年来,前端行业一直在飞速发展.行业的进步,导致对从业人员的要求不断攀升.放眼未来,虽然仅仅会用某些框架还可以找到工作,但仅仅满足于会用,一定无法走得更远.随 ...

  2. 新建项目拷贝html报错,ESA2GJK1DH1K基础篇: 移植源码中SmartConfig程序到自己的项目...

    前言: 说明两个地方 1.点击按钮启动SmartConfig的地方 2.最终跳转的地方 说明 这节说明一下,如何把本人源码里面的SmartConfig程序移植到自己的工程 我要把所有的全部拿出来讲,让 ...

  3. Apache DolphinScheduler 2.X保姆级源码解析,中国移动工程师揭秘服务调度启动全流程...

    2022年1月,科学技术部高新技术司副司长梅建平在"第六届中国新金融高峰论坛"上表示,当前数据量已经大大超过了处理能力的上限,若信息技术仍然是渐进式发展,则数据处理能力的提升将远远 ...

  4. cv::omni::StereoCalibrate 源码解析 (一) —— 单目标定

    cv::omni::StereoCalibrate 的代码逻辑和cv::StereoCalibrate相似. 在opencv库基础上稍微改动. //omni单目标定 输入calibrate(世界坐标系 ...

  5. cv::StereoCalibrate 源码解析 (三)—— 部分函数解析

    cvCalcMatMulDeriv: // reimplementation of dAB.m /*这个矩阵求导和传统的矩阵求导不太一样 求dcda 假设a:M*N c:I*J 最后生成矩阵 IJ * ...

  6. SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy())

    ===================================================== SDL源码分析系列文章列表: SDL2源码分析1:初始化(SDL_Init()) SDL2源 ...

  7. java取负数_[Java] 告别“CV 工程师”码出高效!(基础篇)

    作为一名资深的 CV 工程师,某天,当我再一次日常看见满屏的报错信息与键盘上已经磨的泛白的 Ctrl.C.V 这三个按键时,我顿悟了. 百度谷歌复制粘贴虽然很香,但是总是依靠前人种树,终会有一天失去乘 ...

  8. 如何与资源管理器互动剪切/拷贝/粘贴文件

    一.本文将向读者介绍下面两个问题的解决方案: 1,用户在资源管理器(Windows Explorer)中剪切/拷贝(Cut/Copy)文件,然后在自己的应用程序中进行粘贴(Paste)操作: 2.用户 ...

  9. ChatGPT:新晋CV工程师

    在短短的两个星期内,ChatGPT 迅速成为公众聊天的焦点.超过一百万的人与OpenAI的新聊天机器人"交谈",让它写诗和大学论文,生成创意食谱,创建虚拟机-它也被用来撰写新闻文章 ...

最新文章

  1. php 字符串隔位取,PHP 字符串截取字符串函数
  2. as工程放到源码编译_关于AS高版本SDK编译生成的apk放入低版本android源码中集成编译...
  3. hadoop学习-倒排索引
  4. 数组中子数组求最大和
  5. 阿里云开发者学院电子书《Dubbo分布式服务治理实战》重磅来袭!
  6. linux安装joomla,安装Joomla
  7. php curl http2,用php做ios http2推送服务遇到的坑
  8. 【ArcGIS风暴】捕捉VS经典捕捉,谁更有用武之地?
  9. c语言通讯录程序线性表,数据结构(C语言)课设1——单位员工通讯录管理系统(线性表应用)...
  10. Java编程中“为了性能”尽量要做到的一些地方 [转]
  11. Kotlin 基本数据类型(五)
  12. 渗透实例:The Game Of Bob_1.0.1
  13. html页面酷炫,5个酷炫、实用的HTML标签和属性介绍
  14. Zabbix自定义监控、自动报警
  15. ASP.NET MVC 3 Preview1发布
  16. DataSet-如何优雅使用DataSet,看完此篇文章完全理解C7N/choerodon/猪齿鱼 UI中的DataSet
  17. 微软拼音输入法 2003 精选版 怎么用
  18. 【python】输出列表元素,以空格/逗号为分隔符
  19. 如何用Xbox手柄玩家玩java我的世界,在Gear VR上玩《我的世界》,怎么能少了微软Xbox手柄...
  20. matlab print dmeta,打印图窗或保存为特定文件格式

热门文章

  1. latex中——misplaced \noalign. \hline,\bottomrule,\midrule问题
  2. 互联网医院搭建|慢病管理系统功能板块介绍
  3. html窗口载入完成时间,如何记录页面加载时间
  4. CAD将dwg导出图层
  5. c语言旅店管理系统结构图,C语言 旅店管理系统.doc
  6. Mysql插入10万条模拟数据
  7. 阅读笔记:Instance-aware semantic segmentation via Multi-task Network Cascades
  8. 云原生实践,政务安全大脑,云端密码应用…腾讯在湾区创见大会发布了哪些重点
  9. 代入消元法 matlab,求助 如何用matlab计算期权价格
  10. 关于如何修改VScode中platformio的串口助手默认波特率为115200的问题