在前端平常开发中,对剪贴板相关的操做相对较少。但针对某些特定的应用场景,又是必不可少会用到的。好比:富文本编辑器开发、ctrl + v 上传图片、支付宝红包口令自动复制(典型被玩坏儿了的用途)javascript
操做剪贴板,最基础的方式为监听剪贴板事件。出于兼容性考虑,通常都只在剪贴板事件处理函数中访问 clipboardData ,非 IE 浏览器读数据只能在 onpaste 事件时可用。要使用剪贴板事件读写数据,就必须得用户主动使用快捷键或者右键菜单。因此监听板事件的主要应用场景是用户触发后对数据进行拦截处理。html
document.execCommand() 方法用于操纵可编辑区域的内容,例如最经常使用的 'copy' 命令可将选择区域的内容复制到剪贴板中,配合 window.getSelection() 方法就能够实现自动选择内容区域并写入内容到剪贴板。clipboard.js 库及红包口令自动复制主要就经过此方法实现的。前端
此方法也有一些问题:java
看过上面的介绍,你会发现,操做剪贴板到处受限,并且迂回曲折,更困难的是有些功能是没法实现的。但不能否认,形成这一困惑很大一部分缘由是安全考虑。node
试想一下,当你浏览网页,点了下页面或者按钮,就复制了支付宝红包口令,会怎样?呃,还能接受?那么 'rm -rf /' 呢?(我用 Windows,我怕啥)ios
而作为 Clipboard API 新增内容的 Asynchronous Clipboard API 及 Clipboard Permissions API 就是为了解决上述问题而来的,专治各类迂回曲折及安全风险。截至目前(2018.03),Chrome 66 实现了部分功能,预测将来会有变化,本文不作详细介绍。暂概括特色以下:git
对于粘贴,目前普遍支持的仅有快捷键及右键菜单触发,而 IE 支持的编程方式使用场景很少,这里不作介绍。github
对纯文本的拦截编程
El.addEventListener('paste', event => {
event.preventDefault();
let clipboardData = event.clipboardData || window.clipboardData, // IE 兼容
plainText = clipboardData.getData('text'); // 无格式文本
// ... 对 plainText 进行一系列处理操做
document.execCommand('insertText', false, plainText); // 插入无格式文本
document.execCommand('paste', false, plainText); // IE 兼容
})
复制代码
如需对有格式文本进一步处理,可用如下方法转换为 DOM 结构,再进行操做。(IE 浏览器没法得到 'text/html' 因此没法实现下面的功能)api
/* 仍在上述事件处理函数中,下面均省略 */
let plainHTML = clipboardData.getData('text/html'), // 有格式文本
domContainer = document.createElement('div');
domContainer.innerHTML = plainHTML;
// ... 对 domContainer 进行一系列处理操做
El.innerHTML = domContainer.innerHTML; // 使用 innerHTML 方式总体插入
El.appendChild(nodeOfDomContainer); // 只插入其中某个节点
复制代码
如 DOM 结构中含有图片标签,可考虑上传图片至服务器中,而后将其 src 替换为服务器返回的地址。
如复制的是单个图片(例如 word 中复制过来的),可使用下述方法获得图片的 DataURL,再上传。(IE 浏览器粘贴图片会自动生成带 DataURL 的图片标签,因此不须要下述方法)
let items = clipboardData.items;
for (let i = 0; i < items.length; i++) {
let item = items[i];
if (/image/.test(item.type)) {
let file = item.getAsFile(), // 获得文件对象
reader = new FileReader();
reader.onload = function() {
upload(reader.result) // 上传图片,伪代码
}
reader.readAsDataURL(file); // 读取为 DataURL / Base64
}
}
复制代码
常见应用场景是拦截复制操做,对复制内容加工后再写入剪贴板,例如在知乎复制大段文本后加入版权信息。
El.addEventListener('copy', event => {
event.preventDefault();
let clipboardData = event.clipboardData || window.clipboardData,
text = window.getSelection().toString();
// ... 对 text 进行一系列处理操做
clipboardData.setData('text/plain', text); // 将处理好的 text 写入剪贴板
clipboardData.setData('text', text); // IE 兼容
})
复制代码
虽是编程式复制,但没法作到彻底自动复制,须要用户先触发 点击 事件。clipboard.js 库及红包口令自动复制(在 document 上监听 click 事件)主要就经过此方法实现的。
固定内容
Button.addEventListener('click', event => {
let sometext = '红包码 xxxxxx',
hiddenInput = document.createElement('input');
hiddenInput.value = sometext;
hiddenInput.setAttribute('readonly', '');
hiddenInput.style.position = 'absolute';
hiddenInput.style.left = '-9999px';
document.body.appendChild(hiddenInput);
hiddenInput.select();
hiddenInput.setSelectionRange(0, hiddenInput.value.length); // ios
document.execCommand('copy');
document.body.removeChild(hiddenInput);
})
复制代码
复制某个元素内的文本
Button.addEventListener('click', event => {
let someElement = document.getElementById('someelement'),
selection = window.getSelection(),
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
})
复制代码
能够发现,目前对剪贴板的操做真是千奇百怪,但愿新的 API 快快成为现实吧(
作梦)!
[1] Clipboard API and events | w3c
[3] 利用 javascript 实现富文本编辑器 | 掘金
[4] 富文本编辑器初探 | 掘金