❓️ user-select:none真的能禁止文本的复制粘贴吗?

阿轩的BUG
文章191
评论56
标签101
站点日志
作者总数:1位
置顶文章:0篇
标签总数:101条
文章总数:196篇
评论总数:56条
微语总数:149条
运行天数:2314天
最近更新:2024-09-30
文章标签
最新评论
Sherlock
2025-08-21
不是应该打包成apk文件吗,怎么突然就运行编译了,下一步呢
老金er
2025-05-25
人生设计非常必要,在信息化发达的今天,周围大部分人依然只能过着人生工程模式生活,长时间生活洗礼后,尽管“人生工程”已经不再适合很多人,他们也无法做出任何改变,人生设计给我们提供了新的思路,值得尝试
赏帮赚
2025-05-25
职场太多的尔虞我诈
三笑
2024-08-16
emlog6.0.1可以升级支持吗?
pony
2024-07-08
这篇文章提供了一种新的人生规划方法——"人生设计",它借鉴了产品设计的理念,鼓励人们以创造性和探索性的方式思考和规划自己的生活。以下是对这篇文章的几个评价维度: 创新性:将产品设计的理念应用于人生规划是一个新颖的视角,为人们提供了一种跳出传统生活轨迹,探索个性化生活路径的方法。 实用性:文章不仅提出了理念,还详细介绍了具体的实施步骤,包括自我评估、制定计划、原型设计和实践选择等,具有很强的操作性。 启发性:通过强调好奇心、不断尝试、重新定义问题等心态,文章鼓励人们打破常规,勇于探索未知,这对于激发个人潜能和创造力具有积极作用。 适应性:"人生设计"理念适用于不同人生阶段和不同背景的人,无论是希望从头开始的人,还是已经取得一定成就但希望探索新方向的人,都可以从中获得启发。 情感共鸣:文章对许多人对传统生活轨迹的不满和对改变的渴望进行了深刻的洞察,能够引起读者的共鸣。 可持续性:人生设计强调的是一个持续迭代和试错的过程,这与现实生活的发展规律相吻合,有助于人们在不断变化的环境中做出适应性调整。 教育意义:作为一种人生规划方法,"人生设计"可以作为教育的一部分,帮助年轻人更早地学会自我探索和规划,为未来的生活和职业发展打下基础。 局限性:尽管"人生设计"提供了一种新的思考框架,但它可能需要个人具备一定的自我认知和反思能力,对于一些缺乏自我探索经验的人来说,可能需要额外的指导和支持。 总体来说,这篇文章提供了一种有价值的人生规划方法,对于那些渴望改变、寻求个性化生活的人来说,是一种有益的参考和指导。
首页实用干货 🌋

1. 前言

面向搜索引擎开发时,我们经常看到这样的情况:登录后复制。

由于设置了css属性 user-select:none,此时鼠标无法实现选中文本,也就无法复制文本,通常会采用这种方式来禁止复制文本。打开开发者工具-审查元素,取消此样式,就可以选中文本了。

但是,你们有尝试过这样的复制、粘贴吗?

咦,原来也可以不用登录后复制嘛。??

其实,在记事本、textarea等纯文本框内粘贴是可以通过此属性达到禁止复制的功能,但是在富文本框内粘贴也就无能为力了。

那我们先了解下user-select,然后完善禁止复制的能力。

2. user-select

该属性用来控制用户能否选中文本。其对应常用的值:

  • none:元素及其子元素的文本不可选中。
  • auto:具体取值取决于一系列条件,具体如下:
    • ::before::after 伪元素上,采用的属性值是 none
    • 如果元素是可编辑元素,则采用的属性值是 contain
    • 否则,如果此元素的父元素的 user-select 采用的属性值为 all,则该元素采用的属性值也为 all
    • 否则,如果此元素的父元素的 user-select 采用的属性值为 none,则该元素采用的属性值也为 none
    • 否则,采用的属性值为 text
  • text:用户可以选中文本。
  • all:当单击文本时,会选中这一行文本。

全部值如下:

/* Keyword values */
user-select: none;
user-select: auto;
user-select: text;
user-select: contain;
user-select: all;

/* Global values */
user-select: inherit;
user-select: initial;
user-select: revert;
user-select: revert-layer;
user-select: unset;

3. 选中、复制、粘贴操作

单独选中带有user-select:none的文本样式是无法选中的,但是,我们借用可以选中的文本,虽然中间那个文本是无法看到拖蓝,跨段选中然后复制。

我们发现在富文本框,可以将设置了none的文本正确地粘贴了。前提需要借助可以复制的文本跨段选中。所以前言中“登录后复制”的代码也能使用这种方式,在wps等富文本编辑器中粘贴获得完整代码。

4. user-select:none 如何实现禁止复制文本

在复制文章粘贴时,会发现文本最后会带上版权信息。既然可以悄悄的改动复制的文本内容,那我们也就可以控制哪些文本是否可以复制。

最终我们要实现的效果是,设置了user-select:none的节点,无论在纯文本内还是富文本框内粘贴,都不会粘贴出来,实现了真正的禁止复制,顺便添加版权信息。??

首先,为网页添加copy事件。梦想开始的地方。

采用Selection对象获取到选中的文本,这里面包含了user-select:none节点。

window.addEventListener('copy',()=>{
    const selection = window.getSelection()
    const copyNode = selection.getRangeAt(0).cloneContents();
})

创建一个div,将copyNode放在div内,并挂载到dom树上,以便获取节点的user-select属性值,来控制是否需要复制该节点。

const div = document.createElement('div');
div.appendChild(copyNode);
// 通过getComputedStyle获取style值,需要将节点挂载到dom树上,因此append到body
document.body.appendChild(div);
const nodelist = div.childNodes;
for (let i = 0; i < nodelist.length; i++) {
    const curnode = nodelist[i];
    const nodeType = curnode.nodeType;
    // 重点操作
    // 将节点类型为元素节点,并且设置了user-select:none的节点从复制的内容中过滤掉
    if (nodeType === 1 && window.getComputedStyle(curnode).userSelect === 'none') {
      div.removeChild(curnode);
    }
}
// 获取过滤后的数据
const cpt = div.innerHTML;

将处理好的数据设置为选中,顺便设置个版权信息。

// 又创建个div,将选区设置为此div
const div2 = document.createElement('div');
const copyright = `著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。`
div2.innerHTML = cpt + copyright;
// 要设置选区,需要挂载在dom树上
document.body.appendChild(div2);
// 更新选区
selection.selectAllChildren(div2);

我们创建了2个div,并且append到了页面上,这不应该对用户可见。因此:

  1. 通过设置css,将div放在页面不可见地方
const div2 = document.createElement('div');
+ div2.style.position = 'fixed';
+ div2.style.left = '9999px';
const copyright = `著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。`
  1. 或者在操作最后及时移除节点
// 更新选区
selection.selectAllChildren(div2)
+ setTimeout(() => {
+    document.body.removeChild(div2);
+    document.body.removeChild(div);
+})

以上就是实现完整地禁止复制的全部代码。

5.结语

网上大部分复制文本添加版权的做法是,通过window.getSelection().toString()获取到选中的文本,但是这种方法不会过滤掉设置了user-select:none的文本。

为什么没有通过剪切板去获取复制的文本数据呢? 因为copy事件触发时间是在实际复制操作之前,所以此时剪贴板内还没有数据,曲线救国采用了selection

其次,添加版权信息的做法是,通过window.clipboardData.setData('text', copyNode + copyright)将数据设置到剪贴板上,但是这种方法只能设置纯文本,无法粘贴带样式的文本,但是也可以通过设置新的选区来实现获取富文本数据。

之前在项目里用了此css属性来实现部分敏感信息的禁止复制,自己在开发自测时确实无法选中文本复制,但是上线后,用户反馈文本仍是可以复制并粘贴到同界面的一个富文本框内。后面了解到用户的复制操作是在鼠标拖蓝选中的文本中将不可选中的文本一起复制了,并刚好在富文本框内粘贴,防不胜防啊??。

不过,看到此文的你们一定不会再有此bug!

上一篇
✅ JavaScript 最佳实践:如何写出更可靠、更高性能的代码
下一篇
🎉 通信行程卡-纪念版