聊聊copy复制、cut剪切、paste粘贴事件。
首先这三个事件都属于ClipboardEvent事件(剪切板事件)。什么意思呢?这个三个事件的事件对象event其实都是ClipboardEvent。我们知道浏览器的每个事件的事件对象都是不一样,
wrap.oncopy = function(event){//event就是ClipboardEvent事件
}
wrap.oncut = function(event) { //event就是ClipboardEvent事件
}
wrap.onpaste = function(event) {//event就是ClipboardEvent事件
}
比如,copy事件,打印这个ClipboardEvent事件,看看上面都有哪些属性:
bubbles: true //冒泡
cancelable: true //能否取消
cancelBubble: false //取消冒泡
//以上三个属性:可以冒泡、能够取消冒泡、但没有取消冒泡clipboardData: DataTransfer //clipboardData属性继承DataTransfer对象
composed: true
currentTarget: null
defaultPrevented: false //阻止默认事件
eventPhase: 0
isTrusted: true
path: (5) [div#wrap, body, html, document, Window] //标签path路径
returnValue: true
srcElement: div#wrap
target: div#wrap //事件源对象
timeStamp: 2053.404999896884 //时间戳——从监听到该事件,到该事件触发的时间,单位ms
type: "copy" //事件类型
__proto__: ClipboardEvent //继承的原型对象
任何软件上的内容,可以被复制粘贴,是因为软件对操作系统复制粘贴操作的实现,软件都会把复制剪切的内容存入操作系统的剪切板上,比如,你可以通过Win + V键来查看Windows的剪切板上的内容。
同样,浏览器也对操作系统的剪切板进行了实现,属于浏览器的自身的实现。
浏览器复制操作的默认行为:触发浏览器的copy 事件;将copy的内容存入操作系统的剪切板上;
浏览器的剪切操作的默认行为:如果cut的是可编辑元素内容,会将内容剪切到操作系统的剪切板上,触发浏览器的cut事件;如果是不可编辑的元素内容,不能将内容剪切到操作系统的剪切板上,但是会触发cut事件。
浏览器的粘贴操作的默认行为:将操作系统的剪切板内容粘贴到对应的可编辑区域;触发paste事件。
浏览器的ClipboardEvent事件对象上有个clipboardData属性,该属性值是DataTransfer对象(DataTransfer对象上有setData、getData、clearData方法)。可以通过这三个方法,操作剪切板上的数据。
我们通过document.getSelection();获取页面上的选中内容;
可以通过event.preventDefault();阻止事件的默认行为,即当触发这三个事件时,阻止对系统剪切板的数据操作。
即:我们可以通过event.preventDefault();阻止默认行为,通过ocument.getSelection();获取页面选中内容,再通过DataTransfer对象上的方法,从系统剪切板读取或写入数据。
1、触发:
当用户执行复制操作时,触发copy事件 ,比如:Ctrl+C复制文本、右键复制文本
2、该事件的默认行为:
将所选内容(如果有)复制到系统剪切板上。可以通过event.preventDefault()阻止默认行为。
3、数据:
将选中的数据复制到剪切板上,浏览器低层的实现,与copy事件无关,copy事件只是监听复制行为。
4、element copy event 和 window copy event
copy事件分为element上的copy事件和window的copy事件:
element copy:https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event 兼容IE11
window copy:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/copy_event Edge 18,不兼容IE
<div id="wrap">The Element copy event fires when the user initiates a copy action
through the browser's user interface我是谁我在哪
</div>
<script>
var wrap = document.getElementById("wrap");
wrap.oncopy = function(event){
event.preventDefault();//通过copy事件监听,阻止将选中内容复制到系统剪切板上。
const selection = document.getSelection(); //获取选中内容对象。
var selectContent = selection.toString(); //selection对象重构了toSring()方法,获取selection对象的选中内容
var dealContent = selectContent + "转载请联系作者,内容地址:http://example.com/author/111"
event.clipboardData.setData("text/plain",dealContent)
}
</script>
当复制上面的div内容时,复制到系统剪切板上的内容,会额外的添加"转载请联系作者,内容地址:http://example.com/author/111"字段,这个情况是不是很熟悉呢?
event.preventDefault();//通过copy事件监听,阻止将选中内容复制到系统剪切板上。
const selection = document.getSelection(); //获取选中内容对象。
var selectContent = selection.toString(); //selection对象重构了toSring()方法,获取selection对象的选中内容
event.clipboardData.setData("text/plain",dealContent) //将内容写入到系统剪切板上。
结果:不管在哪个软件上,粘贴内容的时候,都会从剪切板上获取上面实例copy的内容。
1、获取页面选中内容document.selection()得到selection对象
IE9以下支持:document.selection() IE9、Firefox、Safari、Chrome和Opera支持:window.getSelection()
var wrap = document.getElementById("wrap");
wrap.oncopy = function(event){
const selection = document.getSelection();
console.log(selection.toString())//获取选中的内容
}
2、ClipboardEvent上的clipboardData属性:clipboardData属性继承了 DataTransfer对象
所以我们可以通过event.clipboardData.setData()、event.clipboardData.getData()、event.clipboardData.clearData()来操作系统剪切板上的数据。
https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
The ClipboardEvent.clipboardData
property holds a DataTransfer
object。
3、DataTransfer对象上有:setData、getData、clearData方法。
对于某个元素标签而言:
指定应该从cut
和copy
事件处理程序将哪些数据放入剪贴板,通过setData(format, data)
调用;
paste事件用于获取cut、copy事件存入的数据。
通常通过getData(format)
调用从事件处理程序中获取要粘贴的数据。
DataTransfer对象:https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData
setData的参数: format数据类型为text/plain
和text/uri-list
。这里的格式类型有两种,一种是text/plain,另一种是text/uri-list。
setData(format, data)
默认行为是:可以触发cut事件,但是只可以剪切可编辑的元素标签内容,不能剪切非可编辑的元素标签内内容。
如果我们要阻止cut事件的默认对系统剪切板的数据操作行为,那么可编辑的文本也不会有剪切效果。如果向上面的实例那样对数据进行setData的存储,非编辑的内容也会存入到剪切板上。这样就很不妥。
如果某个元素标签的paste事件阻止了默认行为,就无法在该元素标签上进行粘贴操作。
下面实例中,无法在该div标签上进行粘贴操作。
<div id="wrap" contenteditable="true">The Element copy event fires when the user initiates a copy action
through the browser's user interface我是谁我在哪
</div>
<script>
var wrap = document.getElementById("wrap");
wrap.onpaste = function(event){
event.preventDefault();//阻止默认行为,无法在该元素上进行粘贴操作。
}
</script>
以下实例:将剪切板上的内容转为大写;创建一个文本节点,将其插入到指定位置。
<div class="source" contenteditable="true">Try copying text from this box...</div>
<div class="target" contenteditable="true">...and pasting it into this one</div>
<script>
const target = document.querySelector('div.target');
target.addEventListener('paste', (event) => {
let paste = (event.clipboardData || window.clipboardData).getData('text');
paste = paste.toUpperCase();
const selection = window.getSelection();
if (!selection.rangeCount) return false;
console.log(selection.getRangeAt(0))
selection.getRangeAt(0).insertNode(document.createTextNode(paste));
event.preventDefault();
});
</script>
1、可编辑属性:contenteditable,使得标签内容可以被编辑
<div id="wrap" contenteditable="true"></div>