300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 前端js常用剪贴板(复制粘贴)操作和应用 以及navigator.clipboard新粘贴板API使用

前端js常用剪贴板(复制粘贴)操作和应用 以及navigator.clipboard新粘贴板API使用

时间:2021-08-10 00:19:55

相关推荐

前端js常用剪贴板(复制粘贴)操作和应用 以及navigator.clipboard新粘贴板API使用

最近的项目上需要做复制粘贴相关的操作,来总结下吧

复制、剪切、粘贴事件:

copy 发生复制操作时触发;cut 发生剪切操作时触发;paste 发生粘贴操作时触发;

每个事件都有一个 before 事件对应:beforecopy、beforecut、beforepaste;

这几个 before 一般不怎么用,所以我们把注意力放在三个事件就可以了。

触发条件:

鼠标右键菜单的复制、粘贴、剪切;使用了相应的键盘组合键,比如:ctrl+c、ctrl+v;

复制操作:

copy事件使用示例:

<body>gggwgzgf</body><script type="text/javascript">document.body.oncopy = e => {// 监听全局复制 做点什么console.log(e)};</script>

我们可以看到事件对象中的属性:

我们主要研究的是里面的clipboardData属性对象

clipboardData对象:用于访问以及修改剪贴板中的数据

clipboardData对象中有两个方法:

getData():常配合copy事件使用,用于设置到剪贴板中的值

setData():常配合paste事件使用,用于获取设置到剪贴板中的值

兼容:

不同浏览器,所属的对象不同:在 IE

中这个对象是window对象的属性,在Chrome、Safari和Firefox中,这个对象是相应的event对象的属性。所以我们在使用的时候,需要做一下如下兼容:

document.body.oncopy = e => {let clipboardData = e.clipboardData || window.clipboardData;// 获取clipboardData对象 + do something};

copy配合getSelection实现复制某段文本:

<body>gggwgzgf</body><script type="text/javascript">document.body.oncopy = e => {console.log(window.getSelection().toString())let copyMsg = window.getSelection().toString()//把值设置到剪贴板中,方便paste事件触发去拿e.clipboardData.setData("Text", copyMsg);};</script>

为了方便,这次,我直接使用ctrl+c测试了

注意:window.getSelection().toString()我是调用toString()方法转成文本的,如果不调用这个方法,直接通过window.getSelection()取到值存到剪贴板会有出奇的效果,后面会说到,需要配合paste事件

粘贴paste事件

使用示例:

<body>gggwgzgf<input placeholder="这里存放粘贴操作的值" /></body><script type="text/javascript">document.body.oncopy = e => {console.log(window.getSelection().toString())let copyMsg = window.getSelection().toString()e.clipboardData.setData("Text", copyMsg);};document.body.onpaste=function(e){var data = e.clipboardData.getData("Text")document.querySelector("input").value = data}</script>

到这里,你可能有个疑问,只能复制粘贴文本吗,图片可以吗?

这是可以的。

通过patse事件获取剪切板中的图片:

<script type="text/javascript">document.addEventListener('paste', function(event) {var items = (event.clipboardData && event.clipboardData.items) || [];var file = null;if(items && items.length) {for(var i = 0; i < items.length; i++) {if(items[i].type.indexOf('image') !== -1) {file = items[i].getAsFile();break;}}}console.log(file)});</script>

解释:当粘贴事件触发时遍历剪切版对象(clipboardData)中的所有items,找到类型为图片的item并调用getAsFile方法得到文件对象

拿到file对象后我们有几种选择:

通过fileReader得到文件对象的base64字符串

var reader = new FileReader();reader.onload = function(e){// 通过e.target.result取到base64然后上传// 作为src设到image标签上预览}reader.readAsDataURL(file); //此处的file为上面得到的文件对象```

通过formData文件对象转换为二进制数据

var formData = new FormData();formData.append('file', file);

通过URL.createObjectURL转成url地址预览

var blobUrl=URL.createObjectURL(file)

示例代码:

<body><img src="" id="imgTest" /></body><script type="text/javascript">document.addEventListener('paste', function(event) {var items = (event.clipboardData && event.clipboardData.items) || [];var file = null;if(items && items.length) {for(var i = 0; i < items.length; i++) {if(items[i].type.indexOf('image') !== -1) {file = items[i].getAsFile();break;}}}var blobUrl = URL.createObjectURL(file);document.getElementById("imgTest").src = blobUrl;});</script>

局限性:

对于qq,微信等的截图或者按print screen得到的截图,还有任意网页的右击复制图片都能完美支持,但是,对于电脑本地图片文件的复制没办法从剪切版获取到

进阶用法:

配合window.getSelection(),文字图片混合复制粘贴:

<body><span>gegegseraw</span><img src="a1.png" width="100" /><hr />下面为粘贴区域:<div></div></body><script type="text/javascript">document.body.oncopy = function(e) {let copyMsg = window.getSelection()e.clipboardData.setData("Text", copyMsg);}document.body.addEventListener('paste', function(event) {var data = (event.clipboardData && event.clipboardData.items) || [];console.log(data)let div = document.querySelector("div")for(var i = 0; i < data.length; i += 1) {if((data[i].kind == 'string') &&(data[i].type.match('^text/plain'))) {// This item is the target nodeconsole.log("... Drop:plain")} else if((data[i].kind == 'string') &&(data[i].type.match('^text/html'))) {// Drag data item is HTMLdata[i].getAsString(function(s) {div.innerHTML = s});console.log("... Drop: HTML");} else if((data[i].kind == 'string') &&(data[i].type.match('^text/uri-list'))) {// Drag data item is URIconsole.log("... Drop: URI");} else if((data[i].kind == 'file') &&(data[i].type.match('^image/'))) {// Drag data item is an image fileconsole.log("... Drop: File ");}}});</script>

效果:

navigator.clipboard介绍:

异步剪贴板 API是一个相对较新的API,浏览器仍在逐渐实现它。由于潜在的安全问题和技术复杂性,大多数浏览器正在逐步集成这个API。剪贴板Clipboard APINavigator接口添加了只读属性clipboard,该属性返回一个可以读写剪切板内容的Clipboard对象。 在Web应用中,剪切板API可用于实现剪切、复制、粘贴的功能。

系统剪贴板暴露于全局属性Navigator.clipboard之中,Navigator.clipboard对象中有四个常用方法:都是异步的

read():从剪贴板读取数据(比如图片),返回一个 Promise 对象。readText():从操作系统读取文本,返回一个 Promise 对象。write():写入任意数据至操作系统剪贴板,返回一个 Promise 对象。writeText():写入文本至操作系统剪贴板,返回一个 Promise 对象。

注意:只有在用户事先授予网站或应用对剪切板的访问许可之后,才能使用异步剪切板读写方法。许可操作必须通过取得权限 Permissions API 的"clipboard-read"和/或"clipboard-write"项获得。

使用实例:

复制writeText():

navigator.clipboard.writeText('要复制的文本').then(() => {console.log('文本已经成功复制到剪切板');}).catch(err => {// 如果用户没有授权,则抛出异常console.error('无法复制此文本:', err);});

async,await优化写法:

async function copyPageUrl() {try {await navigator.clipboard.writeText(location.href);console.log('Page URL copied to clipboard');} catch (err) {console.error('Failed to copy: ', err);}}

粘贴readText():

navigator.clipboard.readText().then(text => {console.log('Pasted content: ', text);}).catch(err => {console.error('Failed to read clipboard contents: ', err);});

同理也可写成async,await

write()写入数据/图片:

function setClipboard(text) {let data = new DataTransfer();data.items.add("text/plain", text);navigator.clipboard.write(data).then(function() {/* success */}, function() {/* failure */});}

代码创建了一个DataTransfer对象,要替换的内容存储在这里。执行DataTransferItemList.add()将数据写入进去,然后执行write()方法,指定执行成功或错误的结果。

read()读取数据/图片:

navigator.clipboard.read().then(data => {for (let i=0; i<data.items.length; i++) {if (data.items[i].type != "text/plain") {alert("Clipboard contains non-text data. Unable to access it.");} else {textElem.innerText = data.items[i].getAs("text/plain");}}});

应用:

实现类知乎/掘金复制大段文本添加版权信息:

<body><span>0123456789abcdefg</span><hr /> 下面为粘贴区域:<div></div></body><script type="text/javascript">document.body.oncopy = event => {event.preventDefault(); // 取消默认的复制事件let textFont = nulllet copyFont = window.getSelection().toString(); // 被复制的文字 等下插入// 防知乎掘金 复制一两个字则不添加版权信息 超过一定长度的文字 就添加版权信息if(copyFont.length > 10) {textFont =`内容: ${copyFont} 作者:codingWeb 链接:/fesfsefgs来源:csdn 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。`} else {textFont = copyFont; // 没超过十个字 则采用被复制的内容。}event.clipboardData.setData('text', textFont); // 将信息写入粘贴板};document.body.onpaste = function(event) {var data = event.clipboardData.getData("text")document.querySelector("div").innerHTML = data}</script>

实现类起点网的防复制功能:

禁止复制+剪切禁止右键,右键某些选项:全选,复制,粘贴等。禁用文字选择,能选择却不能复制,体验很差。user-select 用 css 禁止选择文本。

// 禁止右键菜单document.body.oncontextmenu = e => {console.log(e, '右键');return false;// e.preventDefault();};// 禁止文字选择。document.body.onselectstart = e => {console.log(e, '文字选择');return false;// e.preventDefault();};// 禁止复制document.body.oncopy = e => {console.log(e, 'copy');return false;// e.preventDefault();}// 禁止剪切document.body.oncut = e => {console.log(e, 'cut');return false;// e.preventDefault();};// 禁止粘贴document.body.onpaste = e => {console.log(e, 'paste');return false;// e.preventDefault();};// css 禁止文本选择 这样不会触发jsbody {user-select: none;-moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;}

提示:使用e.preventDefault()也可以禁用,示例中document.body全局都禁用了,也可以对dom(某些区域)进行禁用。

点击复制功能:

不能使用 clipboardData:

在 IE 中可以用window.clipboardData.setData('text','内容')实现。因为,在 IE

clipboardDatawindow的属性。而其他浏览器则是相应的event对象的属性,这实际上是一种安全措施,防止未经授权的访问,为了兼容其他浏览器,所以我们不能通过clipboardData来实现这种操作。

具体做法:

创建一个隐藏的input框点击的时候,将要复制的内容放进input框中选择文本内容input.select()这里只能用input或者textarea才能选择文本。document.execCommand(“copy”),执行浏览器的复制命令。

示例:

<body><button>#aaaaaa</button><button>#bbbbbb</button><button>#ffffff</button><input /></body><script type="text/javascript">function copyText(e) {var text = e.target.innerHTML; // 获取要复制的内容也可以传进来var input = document.querySelector('input'); // 获取隐藏input的dominput.value = text; // 修改文本框的内容input.select(); // 选中文本document.execCommand('copy'); // 执行浏览器复制命令console.log('复制成功');}document.body.onclick=copyText</script>

扩展:

如果不通过手动点击元素触发click事件,代码控制,我们都知道,可以使用dom.click()触发一次点击操作

那别的事件也可以通过代码控制触发吗?

答案是可以的

事件模拟:

function trigger(el,type){let ev = document.createEvent("HTMLEvents")ev.initEvent(type,true,true)el.dispatchEvent(ev)}

使用:

trigger(domEle,"copy")trigger(domEle,"paste")

键盘模拟:

let mockKeyboardEvent = new KeyboardEvent('keyup', {shiftKey: true, keyCode: 49 })document.dispatchEvent(mockKeyboardEvent)

鼠标模拟:

let mockClickEvent = new MouseEvent('click', {...});document.dispatchEvent(mockClickEvent);

自定义事件模拟:(推荐)

//绑定document.body.onpaste = function (e) {console.log(e)}//触发,携带自定义参数let myEvent = new CustomEvent('paste', {detail: {username: 'aaaaaaa',password: '11111111'}})document.body.dispatchEvent(myEvent)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。