前言
- 作为一名CV工程师,我经常在开发的过程中粘贴复制(纯纯的面向百度编程);
- 但是在某些业务场景中需要我们开发粘贴复制功能;
- 还有些业务场景需要我们去禁用复制功能;
- 下面就来简单说一下基本的复制功能、禁用复制、还有解除禁用复制的基本实现;
一、Vue项目中使用VueUse实现复制功能
- 以下是
Vue3 + TS
的代码;- 如果在想在Vue2中使用VueUse,大家可以百度一下,等俺有空了补充上哈😁;
- 使用
VueUse
提供的useClipboard
函数实现复制功能; - 我们可以在
useClipboard()
里面解构很多东西,但是实现复制功能,我们只需要copy()
函数 和isSupported
属性;
ts
import { useClipboard } from '@vueuse/core';
const { text, copy, copied, isSupported } = useClipboard();
// text ===> 文本
// copy ===> 拷贝函数
// copied ===> 是否拷贝成功,默认 1.5s 恢复状态
// isSupported ===> 是否支持拷贝(权限)
isSupported
===> 是否支持拷贝
- 如果支持拷贝,给
copy()
传入字符串即可;- 只有在https的网站下才能去使用拷贝API,或者本地的localhost这种开发环境才能使用;
- 从权限 Permissions API 获取权限之后,才能访问剪贴板内容;如果用户没有授予权限,则不允许读取或更改剪贴板内容;
- 如果是https环境下,当使用剪贴板权限的时候,浏览器会弹出一个选择面板,如果选择的不授权,就没有拷贝权限,不能拷贝;
- 如果是localhost本地环境,不换痰喘选择面板,默认就是支持拷贝的;
- http网站是不支持的;
copy()
===> 拷贝函数
- 该函数有一个参数,就是需要复制的字符串;
- 该函数的返回值是
Promise
,如果拷贝成功,Promise
就执行成功;
html
<script setup lang="ts">
import { ref } from 'vue';
import { useClipboard } from '@vueuse/core';
import{ showToast } from 'vant';
const { copy, isSupported } = useClipboard();
const text = ref<string>();
/** 复制函数 */
const onCopy = async () => {
// 有权限才能去复制,没有权限就告诉用户没授权,提升用户体验
if (!isSupported.value) return showToast('用户未授权!');
// 这里需要判断,如果 text.value 为 undefined,就复制空串
await copy(text.value || '');
showToast('已复制!');
};
</script>
<template>
<div>
<input v-model="text" placeholder="请输入内容" />
<button @click="onCopy">复制</button>
</div>
</emplate>
<style>
div {
display: flex;
}
input {
font-size: 18px;
}
button {
margin-left: 10px;
}
</style>
- 效果展示
二、原生JS实现复制、禁用复制
2.1 实现复制功能
-
这里就简单使用原生JS实现一下基本的复制功能;
-
下面提供两种复制方法;
-
模板代码:
html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } p { width: 500px; margin: 100px auto; font-size: 20px; } .copy-box { display: flex; justify-content: center; align-items: center; width: 500px; height: 100px; margin: 100px auto; padding: 20px; border: 2px solid red; border-radius: 8px; } input { width: 400px; height: 40px; padding: 10px; font-size: 20px; border-color: #fff; box-shadow: 0 0 10px 1px rgba(0, 0, 0, .2); outline: none; } button { width: 80px; height: 40px; margin-left: 20px; font-size: 20px; outline: none; cursor: pointer; border-radius: 20px; border-color: #fff; box-shadow: 0 0 10px 1px rgba(0, 0, 0, .2); } button:disabled { cursor: not-allowed; } </style> </head> <body> <div class="copy-box"> <input type="text" name="" id="input" autocomplete="off"> <button disabled>复制</button> </div> </body> </html>
2.1.1 ✅ 创建新元素实现复制
- 点击 复制按钮 的时候,使用
documnet.createElement()
创建一个元素(b元素),将 a元素的文本内容(需要赋值的文本)赋值给b元素,使用select()
方法选中创建元素的文本内容,执行复制命令,将复制的文本添加到用户的剪贴板;
疑问:
- 为什么不直接执行a元素的
select()
方法,这样就不用创建元素,直接将选中的文本添加到用户的剪贴板???
- 这样也是可以的,但是会有问题,就是执行a元素的
select()
方法后,a元素中的文本内容的状态就是选中状态(整段文字的背景颜色是蓝色);- 如果当前部门业务那边对这一点没有意见的话,就可以直接使用这种方法(详细看2.1.1);
- 关于选中状态之后的变化,下一小节详细说一下;
- 当前小结只关注使用创建元素实现复制功能;
- 基于上述模板代码;
js
/**
* 复制函数
* @param { string } text 需要复制的文本内容
* @returns { void }
*/
function copyToClipboard(text) {
// 看当前需求,如果用户没有输入内容也能复制的话,就将 button 元素的 disabled 属性去掉,用户复制的就是空串;
// 还有一种就是不禁用按钮,但是当用户没有输入内容就去点击复制的话,我们可以去给用户一个提示;
// 创建元素
const copyFrom = document.createElement('textarea');
// 设置元素的内容
copyFrom.value = text;
// 将创建的元素添加到body中
document.body.appendChild(copyFrom);
// 选中元素
copyFrom.select();
// 执行复制命令,将文本添加到用户的剪贴板
document.execCommand('copy');
// 删除创建的元素
document.body.removeChild(copyFrom);
}
// 获取 input 元素
const input = document.querySelector('#input');
// 获取 button 按钮
const btn = document.querySelector('button');
// 给 button 元素 绑定事件
button.addEventListener('click', () => {
copyToClipboard(input.value);
alert('复制成功!');
});
- 效果演示:
2.1.2 复制现有元素的文本
- 在点击复制按钮的时候,使用
select()
选中input元素的值,将input
的值添加到用户的剪贴板即可; - 问题 :
- 使用
select()
方法之后,文本的状态会变成选中状态(选中的文本背景颜色变为蓝色);
- 使用
- 解决问题 :
- 修改选中文本的背景颜色;
- 基于上述模板代码;
js
// 获取元素
const btn = document.querySelector('button');
const input = document.querySelector('#text');
// 监听input的输入事件,有值就解除button按钮的禁用状态
input.addEventListener('input', (e) => {
if (e.target.value) btn.removeAttribute('disabled');
else btn.setAttribute('disabled', true);
});
// 给button按钮绑定事件
btn.addEventListener('click', (e) => {
try {
// 选中input框中的文本
input.select();
// 将选中的文本复制到剪贴板
document.execCommand('copy');
alert('复制成功!');
} catch (err) {
console.log(err);
}
});
-
效果演示:
-
修改选中文本的背景颜色:
::selectio
该伪类选择器的可选属性有四个,分别是:color、background、cursor、outline
;css#input::selection { // 将选中文本的背景颜色改为透明色 background: transparent; } // 火狐浏览器 #input::-moz-selection { // 将选中文本的背景颜色改为透明色 background: transparent; }
js
<script>
// 监听整个文件流的复制
document.addEventListener('copy', function (e) {
// 阻止浏览器的默认行为,不让复制
e.preventDefault();
// 给用户的剪贴板里面增加一些数据
// e.clipboardData ===> 剪贴板对象
// text/plain ===> 纯文本数据
e.clipboardData.setData('text/plain', '复制成功');
});
</script>
2.2 禁用复制
-
模板代码:
html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> p { width: 500px; margin: 100px auto; font-size: 20px; } </style> </head> <body> <p> In the flood of darkness, hope is the light. It brings comfort, faith, and confidence. It gives us guidance when we are lost, and gives support when we are afraid. And the moment we give up hope, we give up our lives. The world we live in is disintegrating into a place of malice and hatred, where we need hope and find it harder. In this world of fear, hope to find better, but easier said than done, the more meaningful life of faith will make life meaningful. </p> </body> </html>
-
在JS的事件中,有个
copy
事件 ,当检测到 复制 的时候会 触发该事件;
事件对象.clipboardData
===> 剪贴板对象 提供了以下方法:
setData(type, data)
:
- 将指定的 type 类型的数据设置为剪贴板的内容。data 参数是要设置的数据。
getData(type)
:
- 返回剪贴板中指定 type 类型的数据。如果找不到指定类型的 data,则返回 null。
clearData()
:
- 清除剪贴板中所有类型的数据。
readData()
:
- 返回一个包含剪贴板中所有类型的数据的对象。
- ❗❗ 注意 :
e.clipboardData
对象只在'copy'
事件中可用。
-
代码展示:
js// 监听复制事件 document.addEventListener('copy', (e) => { // 阻止默认行为 - 复制行为 e.preventDefault(); // 给用户的剪贴板设置文本数据 e.clipboardData.setData('text/plain', '复制成功!'); alert('复制一次1块钱!'); // 相关逻辑 - 弹出一个微信收款码😂😂 });
三、解除禁用复制
- 解除禁用复制用的最多的莫过于我们去一些网站复制文本的时候,他不让我们复制,还要收费,直接就是干他😡;
- 废话不多说,直接上动画,以各位的聪明才智,一看就懂: