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

本文介绍了前端JavaScript中复制、剪切、粘贴事件的使用,详细讲解了如何利用clipboardData对象进行数据交互,并探讨了navigator.clipboard新API的异步读写方法,包括writeText、readText、write、read等,同时提供了在实际项目中的应用案例,如添加版权信息和防复制功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

复制、剪切、粘贴事件:

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

每个事件都有一个 before 事件对应:beforecopy、beforecut、beforepaste;
这几个 before 一般不怎么用,所以我们把注意力放在三个事件就可以了。

触发条件:

  1. 鼠标右键菜单的复制、粘贴、剪切;
  2. 使用了相应的键盘组合键,比如: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 对象后我们有几种选择:

  1. 通过fileReader得到文件对象的base64字符串
var reader = new FileReader();
reader.onload = function(e){
// 通过e.target.result取到base64然后上传
// 作为src设到image标签上预览
}
reader.readAsDataURL(file); //此处的file为上面得到的文件对象```
  1. 通过formData文件对象转换为二进制数据
var formData = new FormData();
formData.append('file', file);
  1. 通过 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 node
					console.log("... Drop:plain")
				} else if((data[i].kind == 'string') &&
					(data[i].type.match('^text/html'))) {
					// Drag data item is HTML
					data[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 URI
					console.log("... Drop: URI");
				} else if((data[i].kind == 'file') &&
					(data[i].type.match('^image/'))) {
					// Drag data item is an image file
					console.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 = null
			let copyFont = window.getSelection().toString(); // 被复制的文字 等下插入
			// 防知乎掘金 复制一两个字则不添加版权信息 超过一定长度的文字 就添加版权信息
			if(copyFont.length > 10) {
				textFont =`
					内容: ${copyFont} 
					作者:codingWeb 
					链接:https://blog.csdn.net/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>	

在这里插入图片描述


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

  1. 禁止复制+剪切
  2. 禁止右键,右键某些选项:全选,复制,粘贴等。
  3. 禁用文字选择,能选择却不能复制,体验很差。
  4. 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 禁止文本选择 这样不会触发js
body {
    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来实现这种操作。

具体做法:

  1. 创建一个隐藏的input框
  2. 点击的时候,将要复制的内容放进input框中
  3. 选择文本内容input.select()
  4. 这里只能用input或者textarea才能选择文本。
  5. 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的dom
			input.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)

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codingWeb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值