前端知识库(lizh)
  • README
  • Bugs
    • 前端调试随笔
    • 浏览器常见问题概览
    • 浏览器兼容问题概览
    • HTML常见问题概览
    • CSS常见问题概览
    • JS常见问题概览
    • 移动端兼容性问题概览
    • 微信小程序开发
    • NodeJs常见问题概览
    • Mac常见问题概览
    • 微信开发遇坑指南
    • Npm包常见问题概览
    • 其他问题汇总
  • Css探索系列
    • CSS基础知识
    • CSS常见问答
    • CSS常见问答02
    • CSS应用示例
    • CSS应用示例02
    • 由Z Index引发的层叠上下文思考
    • 由浮动塌陷引发的块级格式上下文思考
    • CSS探索系列 Flex布局
    • CSS探索系列 Margin
    • CSS探索系列 Auto关键字
    • CSS探索系列 Gradient
    • CSS探索系列 Line Height
    • CSS探索系列 元素居中
    • CSS探索系列 动画
    • 为什么使用PostCSS处理CSS?
    • 重新认识伪类与伪元素
    • 自定义表单伪元素样式
    • 如何理解Css中的Display属性
    • 视口和软键盘对视口的影响
    • 关于Css
  • Frontend
    • 00 关于Web前端
    • 01 前端知识概览
    • 02 常用前端库概览
    • 基础 00 前端常见问题01
    • 基础 01 浏览器缓存
    • 基础 02 浏览器工作原理
    • 基础 03 谈谈前端跨源问题及解决方法
    • 进阶 01 Web性能优化
    • 进阶 02 搜索引擎优化(SEO)
    • 进阶 03 前端模块化编程
    • 进阶 04 规范代码:Linter、Prettier、EditorConfig
    • 进阶 11 前端自动化测试
    • 高级 01 前端安全
    • Vue2.X原理篇
    • Vue3初步了解及迁移指南
    • 重读Vue教程
    • React17.X原理篇
    • 你必须知道的React问题
    • 重读React教程
    • 聊一聊Cookie的一些问题
    • 如何理解HTTP响应的状态码
    • HTTP的历史演变及概述
    • Webpack4.X原理篇
    • Webpack基础入门篇
    • Webpack构建优化篇
    • TypeScript使用指南
    • 代码规范
      • 前端规范
      • HTML
      • CSS
      • JS
  • Html探索系列
    • HTML基础知识
    • HTML基础知识02
    • HTML常见问答
    • HTML经典实践用例
    • HTML元素的宽高及位置详解
    • Video元素的使用和常见问题总结
    • Html探索系列 Meta标签
    • DOCTYPE:文档类型与浏览器模式
    • DHTML(动态网页)简介
    • HTML标签详解
    • HTML布局的几种方式
    • HTML全局属性
    • 关于Html
  • Js探索系列
    • 基础知识
    • 常见问答
    • 应用示例
    • 趣味示例
    • 基础篇 05 AJAX
    • 基础篇 06 Window对象
    • 基础篇 07 Error、JSON、Math、Console对象
    • 基础篇 08 History、URL、Screen、Navigator、Location对象
    • 基础篇 09 文档对象模型(DOM)
    • 基础篇 10 Document对象
    • 基础篇 11 Element对象
    • 基础篇 12 Event对象
    • 基础篇 13 键盘、鼠标、触摸事件
    • 基础篇 15 CSS对象模型(CSSOM)
    • 进阶篇 01 Prototype对象和继承
    • 进阶篇 02 Promise对象
    • 进阶篇 07 迭代器(Iterator)
    • 进阶篇 08 Generator和Async函数
    • 进阶篇 09 JavaScript异步编程
    • Date对象和日期时间字符串格式
    • Canvas基础入门篇
    • Canvas进阶篇
    • SVG基础入门篇
    • 四种判断数据类型方法的优缺点
    • 深入理解JavaScript的浅拷贝和深拷贝
    • 谈谈JavaScript的作用域和上下文
    • 复制内容到剪贴板
    • 关于Javascript
  • NodeJs
    • 关于Node.Js
    • Node.Js:三种调试方法
    • Npm包管理器简介及一些机制
    • NPM:Package.Json详解(中文)
    • NPM:从零开始,开发一个软件包
    • NPM:常用命令
    • Node.Js:Fs(文件系统)
    • Node.Js:Global(全局变量)
    • Node.Js:HTTP
    • Node.Js:Module(模块)
    • Node.Js:Path(路径)
    • Node.Js:Readline(逐行读取)
  • Research
    • 极细边框(1px边框)实现方式
    • 如何监控前端异常?
    • H5页面跳转和刷新
    • Web主题切换和个性化定制方法总结
    • Vue SSR(服务端渲染)的简单实现
    • 基于Create React App打造代码规范化的React+Ts项目
    • H5可视化编辑
    • Web常用功能
    • Javascript加密混淆
    • Vue如何导入TypeScript
    • 移动端PDF预览
    • 纯CSS绘制箭头
    • 网站性能测量和优化方法
  • Tech
    • GOOGLE浏览器的搜索技巧
    • Curl的用法指南
    • Sublime3插件篇
    • Charles安装及使用
    • Nginx基础使用
    • 排序算法(Javascript)
    • 代码整洁之道(摘录笔记)
    • Java的24种设计模式与7大原则
    • 观察者和发布订阅模式
  • Tools
    • Git
      • Git基础教程
      • Git常见问题
    • Gitbook
      • Gitbook入门篇
      • Gitbook插件篇
      • Gitbook进阶篇
由 GitBook 提供支持
在本页
  • document.execCommand()
  • 复制操作
  • 剪切操作
  • 粘贴操作
  • Clipboard API
  • Permissions
  • 复制:将文本写入剪贴板
  • 粘贴:从剪贴板中读取文本
  • 剪贴板事件
  • 参考资料

这有帮助吗?

  1. Js探索系列

复制内容到剪贴板

JavaScript 有两种方式可以让浏览器与系统剪贴板交互:Document.execCommand() 方法以及现代的异步的 Clipboard API。

document.execCommand()

document.execCommand() 方法允许运行命令来操纵可编辑内容区域(即元素的 contenteditable 属性值为true)的元素。

document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)

该方法返回布尔值,表示操作是否被支持或启用。

  • aCommandName: 字符串,命令的名称:copy、cut、delete、forwardDelete(删除光标所在位置的字符)、paste、selectAll(选中编辑区里的全部内容)等等。

  • aShowDefaultUI: 布尔值, 是否展示用户界面,一般为 false。(Mozilla 没有实现)。

  • aValueArgument: 一些命令需要的额外参数。

document.execCommand() 方法常用指令:

// 各种浏览器都支持:复制、剪切和粘贴这三个操作
document.execCommand('copy')
document.execCommand('cut')
document.execCommand('paste')

已废弃: document.execCommand() 特性已经过时了。 虽然它可能仍然在一些浏览器中工作,但它的使用是不鼓励的,因为它可能随时被删除。 尽量避免使用它。

复制操作

document.execCommand('copy') 命令用于将选中的文本内容写入剪贴板。该命令无需任何特别的权限就可以使用。

const inputDom = document.querySelector('#input')
inputDom.select()
document.execCommand('copy')

默认情况下,document.execCommand('copy') 只能将选中的文本内容写入到剪贴板。以下方法实现写入任意文本到剪贴板:

function fnExecCommandCopy(str) {
    let inputDom = document.createElement("input")
    document.body.appendChild(inputDom)
    inputDom.value = str
    inputDom.focus()
    inputDom.select()
    if (document.execCommand("copy")) {
        console.log("复制成功")
    } else {
        console.log("不支持复制")
    }
    inputDom.blur()
    document.body.removeChild(inputDom)
}

注意: 复制操作最好放在事件监听函数里面,由用户触发(比如用户点击按钮)。如果脚本自主执行,某些浏览器可能会报错。

注意: document.execCommand('copy') 是同步操作,如果复制/粘贴大量数据,页面会出现卡顿。有些浏览器还会跳出提示框,要求用户许可,这时在用户做出选择前,页面会失去响应。

剪切操作

document.execCommand('cut') 命令用于将选中的文本内容写入剪贴板,同时删除选中的内容。

const inputDom = document.querySelector('#input')
inputDom.select()
document.execCommand('cut')

粘贴操作

document.execCommand('paste') 命令用于将剪贴板里面的文本内容取出,输出到当前的焦点元素中。

const inputDom = document.querySelector('#input')
inputDom.focus()
document.execCommand('paste')

注意: 出于安全考虑,浏览器通常不允许 document.execCommand('paste') 访问剪贴板,因为它可能包含敏感信息。因此,该命令一般是不启效的。

Clipboard API

Clipboard 接口实现了 Clipboard API,如果用户授予了相应的权限,就能提供系统剪贴板的读写访问。Clipboard 对象是通过 navigator.clipboard 属性返回,所有剪贴板操作都通过这个对象进行。

该 API 被设计用来取代使用 document.execCommand() 的剪贴板访问方式。

使用 Clipboard API 需要注意以下问题:

  • 异步的 Clipboard API 方法是一个近期新增的规范,并且这个规范可能不适用于所有浏览器。

  • Chrome 浏览器规定,只有 HTTPS 协议的页面才能使用这个 API。不过,开发环境(localhost)允许使用非加密协议。

  • 调用时需要明确获得用户的许可。权限的具体实现使用了 Permissions API,跟剪贴板相关的有两个权限: clipboard-read 和 clipboard-write 。clipboard-write 自动授予脚本,而 clipboard-read 必须用户明确同意给予。也就是说,写入剪贴板,脚本可以自动完成,但是读取剪贴板时,浏览器会弹出一个对话框,询问用户是否同意读取。

  • **脚本读取的总是当前页面的剪贴板。**也就是说,如果把相关的代码粘贴到开发者工具中直接运行,可能会报错,因为这时的当前页面是开发者工具的窗口,而不是网页页面。

Permissions

Permissions API 提供以下方法:

  • query(): 返回给定 API 的用户权限状态。

  • request(): 请求使用给定 API 的权限。目前任何浏览器都不支持此功能。

  • requestAll(): 请求使用一组给定 API 的权限。目前任何浏览器都不支持此功能。

  • revoke(): 撤销当前在给定 API 上设置的权限。

以下是查看是否有 clipboard-read 权限的方法:

navigator.permissions.query({name:'clipboard-read'}).then(function(result) {
    if (result.state === 'granted') {
        console.log('granted')
        return
    }
    if (result.state === 'prompt') {
        console.log('prompt')
        return
    }
    console.log('fail')
})

遗憾的是,目前为止,浏览器还不支持 Permissions.request()、Permissions.requestAll() 这两个申请权限的方法。我们可以尝试用 Chrome 插件来开放 Clipboard 权限。

复制:将文本写入剪贴板

使用 Clipboard API 的 writeText() 或 write() 方法来将数据写入剪贴板。Clipboard API 比 execCommand 更加灵活,因为你不仅可以将当前选中的内容写入到剪贴板,还可以指定要写入剪贴板的内容。

**注意:**请先确认是否有 Permissions API 的 clipboardWrite 权限。因为这是一个新的 API,不同浏览器的具体要求不同。

writeText() 方法用于写入特定字符串到操作系统的剪贴板:

navigator.clipboard.writeText("霁光浮瓦碧参差。").then((res) => {
    console.log('writeText:写入成功!')
}).catch((err) => {
    console.log(err)
})

write() 方法用于将任意数据写入剪贴板,可以是文本数据,也可以是二进制数据,如图片。

需要注意的是: write() 方法的传参必需一个 ClipboardItem 实例。

navigator.clipboard.write([
    new ClipboardItem({
        "text/plain": new Blob(['要复制的文本'], { type: "text/plain" })
    })
]).then((res) => {
    console.log('write:写入成功!')
}).catch((err) => {
    console.log(err)
})
const image = await fetch('tupian_27781.png').then(response => response.blob())
const text = new Blob(['一夕轻雷落万丝,\n霁光浮瓦碧参差。\n有情芍药含春泪,\n无力蔷薇卧晓枝。'], {type: 'text/plain'})
const data = new ClipboardItem({
    'text/plain': text,
    'image/png': image
})
navigator.clipboard.write([data]).then(() => {
    console.log('write:写入成功!')
}).catch((err) => {
    console.log(err)
})

粘贴:从剪贴板中读取文本

使用 Clipboard API 的 readText() 和 read() 方法可从剪贴板读取任意文本或二进制数据。

readText() 方法用于读取剪贴板的文本数据。注意:在尝试读取剪贴板的内容时,浏览器会提醒用户是否允许该请求:

navigator.clipboard.readText().then((res) => {
    console.log(`readText:${res}`)
}).catch((err) => {
    console.log(err)
})

read() 方法用于读取剪贴板的数据,与 readText() 的不同是,该方法可以读取剪贴板中的任意数据,如图片:

navigator.clipboard.read().then(data => {
    data.forEach(item => {
        item.types.forEach(async (type) => {
            let readRes = await item.getType(type)
            switch(type) {
                case 'text/plain': {
                    let tx = await readRes.text()
                    console.log(tx)
                    break
                }
                case 'image/png': {
                    console.log(URL.createObjectURL(readRes))
                    break
                }
                default: {
                    console.log('未处理的数据类型!')
                    break
                }
            }
        })
    })
}).catch(err => {
    console.error('无法读取剪贴板: ', err)
})

剪贴板事件

剪贴板有3个操作: 复制、剪切、粘贴。这3个操作共对应下列 6 个剪贴板事件:

  • copy: 复制时触发;

  • cut: 剪切时触发;

  • paste: 粘贴时触发;

  • beforecopy: 复制前触发;

  • beforecut: 剪切前触发;

  • beforepaste: 粘贴前触发。

注意: 后三个事件,浏览器不一定支持。比如:Chrome 只支持 beforecopy、beforecut,不支持 beforepaste。

通常,我们只需要关注前三个事件即可:

document.addEventListener('copy', (event) => {});
document.addEventListener('cut', (event) => {});
document.addEventListener('paste', (event) => {});

这三个事件的触发条件:

  • 快捷键: ctrl+c、ctrl+x、ctrl+v 操作。

  • 鼠标右键菜单:复制、剪切、粘贴操作。

  • execCommand:copy、cut、paste 指令。

特别注意: 这三个事件在使用异步 Clipboard API 访问剪贴板时不会触发。

document.addEventListener('copy', (event) => {
    event.preventDefault()
    event.clipboardData.setData('text/plain', 'COPY ME!!!')
    event.clipboardData.setData('text/html', '<p>COPY ME!!!</p>')
})

event.clipboardData 有以下属性和方法:

  • setData(type, data): 修改剪贴板数据,需要指定数据类型。

  • getData(type): 获取剪贴板数据,需要指定数据类型。

  • clearData([type]): 清除剪贴板数据,可以指定数据类型。如果不指定类型,将清除所有类型的数据。

  • items: 一个类似数组的对象,包含了所有剪贴项,不过通常只有一个剪贴项。

参考资料

上一页谈谈JavaScript的作用域和上下文下一页关于Javascript

最后更新于1年前

这有帮助吗?

在剪贴板事件中,可以调用 event.preventDefault() 取消剪贴板操作,并且剪贴板 event 对象有一个 clipboardData 属性,它是一个 对象。它允许我们覆盖将写入剪贴板的数据,让我们有机会以其他格式写入数据,例如 text/html:

查看剪贴板读写DEMO
DataTransfer
MDN Clipboard
MDN Interact with the clipboard
MDN Permissions
MDN DataTransfer
异步剪贴板 API:使用 JavaScript 访问剪贴板
阮一峰 剪贴板操作 Clipboard API 教程