我们先来提几个场景,比如我们想要在网页上复制一段文字,结果会提示不允许复制;还有某音或者某宝分享的时候也是发一段文字过去,复制以后打开就会跳转到对应页面;还有就是复制一段文字,粘贴的时候发现除了原有文字还会给你加上一些东西。这些操作都可以通过Clipboard API去完成。
Clipboard API分为两个部分,一个部分是一个对象,放在navigator.clipnoard中,这里面提供了一些方法供我们操作剪贴板。除了这个对象以外,还提供了一套事件,就是当用户在页面进行复制或者粘贴的时候,会触发相应的事件。我们通过这两个东西就可以完成绝大部分的操作了。
1.不允许复制
这个时候我们就要去监听它的复制事件了,复制事件是copy。
document.addEventListener('copy', (e) => {
console.log('内容已复制到剪贴板!');
});
如果我们不想让其被复制,我们可以组织事件的默认行为,让其不能被复制。
document.addEventListener('copy', (e) => {
// 阻止默认行为
e.preventDefault();
});
我们先去复制一条别的内容,然后再复制我们网页上的内容,在粘贴的时候会发现粘贴的还是上一次的内容,因为网页上的内容不会进入剪贴板,这么一来就不能被复制了。
2.往剪贴板里面去添加东西
我们可以通过navigator.clipnoard的一些方法去操作剪贴板,比如不让用户复制内容,但是往剪贴板里面添加一段文字,让其在粘贴的时候粘贴上去的是我们添加的文字,一般用于版权相关的操作。
document.addEventListener('copy', (e) => {
e.preventDefault();
navigator.clipboard.writeText('版权归月亮所有,翻版必究!');
});
我们也可以让其复制内容,不过在末尾加上我们的自定义内容。
<template>
<div class="screen-view">
<div class="txt">我是要被复制的内容!</div>
</div>
</template>
<script>
export default {
name: 'Clipboard',
data() {
return {}
},
mounted() {
let txt = document.querySelector('.txt');
document.addEventListener('copy', () => {
// 因为文本是divDOM节点,所以要用innerText获取文本内容,如果是input或者textarea,则用value获取文本内容
navigator.clipboard.writeText(txt.innerText + '版权归月亮所有,翻版必究!');
});
},
}
</script>
而且navigator.clipboard.writeText返回的是一个promise,所以我们可以在后面添加then方法或者catch方法。
let txt = document.querySelector('.txt');
document.addEventListener('copy', () => {
// 因为文本是divDOM节点,所以要用innerText获取文本内容,如果是input或者textarea,则用value获取文本内容
navigator.clipboard.writeText(txt.innerText + '版权归月亮所有,翻版必究!').then(() => {
console.log('复制成功');
}).catch(err => {
console.log('复制失败', err);
});
});
3.读取剪贴板内容,然后做出相应事件
这一点就用于某音或者某宝分享东西了,首先我们要先读取剪贴板,我们可以通过navigator.clipboard.readText()事件去读取,这返回的也是一个promise,所以我们通过then方法去做一些后续操作,比如跳转某个页面啊,我这里的是把剪贴板的内容复制到页面上,因为这个方法我直接写在mounted事件里的,所以需要刷新一下页面去触发。
mounted() {
let txt = document.querySelector('.txt');
navigator.clipboard.readText().then(res => {
// 读取剪贴板内容赋值到txt
txt.innerText = res
})
},
4.复制图片
平时图片我们也可以直接复制到页面上。
<template>
<div class="screen-view">
<!-- contenteditable属性可以让div变成可编辑状态 -->
<div class="editor" contenteditable></div>
</div>
</template>
<script>
export default {
name: 'Clipboard',
data() {
return {}
},
mounted() {
},
}
</script>
<style lang='scss'>
.screen-view {
height: 100%;
padding: 10px;
box-sizing: border-box;
.editor {
width: 400px;
height: 300px;
border: 1px solid #ccc;
img {
max-width: 100% !important;
}
}
}
</style>
但是这有两个缺陷,一是不能保证所有浏览器都有这个功能,二是这个只能复制截图,我们要是复制一个别的图片比如放在桌面上的图片,这么一来就复制不上去了。
那么我们该怎么做呢,首先我们要去监听一个事件叫做粘贴事件paste,在这里它会提供一个对象叫做clipboardData,当我们粘贴的是类似于图片这种东西的时候clipboardData会有一个属性叫做files。我们打印看一下。
document.addEventListener('paste', (e) => {
console.log(e.clipboardData.files);
});
当我们粘贴的是一个文本的时候,会发现这个files长度为0,没有任何东西。
当我们粘贴的是一个图片的时候,会发现里面有东西了,每一项都是你粘贴的图片文件,打开就是文件的信息。
所以我们就可以获取files里的东西去操作,让其复制到页面上,首先得阻止事件的默认行为,就是不用浏览器的粘贴方式,然后获取文件,前面我们看到文件信息里有一个属性叫做type,我们可以根据这个去判断是图片还是文档还是什么别的东西,然后进行对应操作。
<template>
<div class="screen-view">
<!-- contenteditable属性可以让div变成可编辑状态 -->
<div class="editor" contenteditable></div>
</div>
</template>
<script>
export default {
name: 'Clipboard',
data() {
return {}
},
mounted() {
document.addEventListener('paste', (e) => {
// 大于0表示剪贴板中有文件
if (e.clipboardData.files.length > 0) {
// 首先阻止浏览器的默认粘贴行为,不用浏览器默认粘贴方式
e.preventDefault();
// 获取粘贴的文件
const file = e.clipboardData.files[0];
// startsWith() 方法用于检测字符串是否以指定的子字符串开头
if (file.type.startsWith('image/')) {
// 如果是图片文件,创建一个URL并插入到编辑器中
// URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含表示参数对象的 URL
const imgURL = URL.createObjectURL(file);
const img = document.createElement('img');
// 将创建的URL赋值给img的src属性
img.src = imgURL;
document.querySelector('.editor').appendChild(img);
// 当不再需要该对象URL时,应该通过调用 URL.revokeObjectURL() 来释放它
img.onload = () => {
URL.revokeObjectURL(imgURL);
};
} else {
alert('仅支持粘贴图片');
}
}
});
},
}
</script>
<style lang='scss'>
.screen-view {
height: 100%;
padding: 10px;
box-sizing: border-box;
.editor {
width: 400px;
height: 300px;
border: 1px solid #ccc;
img {
max-width: 100% !important;
}
}
}
</style>
可以看到这样就可以把图片复制到页面上了,关于图片的操作还有一种是使用读取器的方法。
document.addEventListener('paste', (e) => {
// 大于0表示剪贴板中有文件
if (e.clipboardData.files.length > 0) {
// 首先阻止浏览器的默认粘贴行为,不用浏览器默认粘贴方式
e.preventDefault();
// 获取粘贴的文件
const file = e.clipboardData.files[0];
// startsWith() 方法用于检测字符串是否以指定的子字符串开头
if (file.type.startsWith('image/')) {
// 如果是图片
// 创建FileReader对象
const reader = new FileReader();
// 读取文件内容,形成一个base64编码的URL
reader.readAsDataURL(file);
// 当读取操作完成时触发
reader.onload = (event) => {
const img = document.createElement('img');
// event.target.result就是读取到的图片base64编码
img.src = event.target.result;
// 将图片插入到可编辑的div中
document.querySelector('.editor').appendChild(img);
};
} else {
alert('仅支持粘贴图片');
}
}
});
当然除了读取图片以外我们也可以去读取文档,我已经创建好了两个文档,一个是doc文档,一个是docx文档。我们先来看一下这两个文档打印出来的内容是什么。
可以看到type都是application/开头的,那么接下来就去做判断就好了。
<template>
<div class="screen-view">
<!-- contenteditable属性可以让div变成可编辑状态 -->
<div class="editor" contenteditable></div>
</div>
</template>
<script>
export default {
name: 'Clipboard',
data() {
return {}
},
mounted() {
document.addEventListener('paste', (e) => {
// 大于0表示剪贴板中有文件
if (e.clipboardData.files.length > 0) {
// 首先阻止浏览器的默认粘贴行为,不用浏览器默认粘贴方式
e.preventDefault();
// 获取粘贴的文件
const file = e.clipboardData.files[0];
console.log(file);
// startsWith() 方法用于检测字符串是否以指定的子字符串开头
if (file.type.startsWith('image/')) {
// 如果是图片
// 创建FileReader对象
const reader = new FileReader();
// 读取文件内容,形成一个base64编码的URL
reader.readAsDataURL(file);
// 当读取操作完成时触发
reader.onload = (event) => {
const img = document.createElement('img');
// event.target.result就是读取到的图片base64编码
img.src = event.target.result;
// 将图片插入到可编辑的div中
document.querySelector('.editor').appendChild(img);
};
} else if (file.type.startsWith('application/')) {
// 如果是文件
// 创建FileReader对象
const reader = new FileReader();
// 读取文件内容,形成一个base64编码的URL
reader.readAsDataURL(file);
// 当读取操作完成时触发
reader.onload = (event) => {
const link = document.createElement('a');
// event.target.result就是读取到的文件base64编码
link.href = event.target.result;
link.download = file.name; // 设置下载文件名
link.textContent = `点击下载 ${file.name}`;
// 将链接插入到可编辑的div中
// 不插入到editor这个div 是因为有了 contenteditable 属性以后就没法点击了
document.querySelector('.screen-view').appendChild(link);
};
} else {
alert('请粘贴图片或文件');
}
}
});
},
}
</script>
<style lang='scss'>
.screen-view {
height: 100%;
padding: 10px;
box-sizing: border-box;
.editor {
width: 400px;
height: 300px;
border: 1px solid #ccc;
img {
max-width: 100% !important;
}
}
}
</style>